openapi: 3.0.3
info:
  title: NLX Conversational AI API
  version: 2.0.0
  description: |
    A comprehensive RESTful API for natural language understanding and conversational AI capabilities.

    # Getting Started
    
    ### For Conversation API
    You need:
    1. **Deployment Key**: Found in your application's deployment details
    2. **Channel Key**: The specific channel identifier (may include language suffix like `-en-US`)
    3. **API Key**: Provided in your channel setup instructions
    
    ### For Voice+ Script API
    You need:
    1. **Voice+ API Key**: Generated for your Voice+ journey/script
    2. **Workspace ID**: Your NLX workspace identifier
    3. **Script ID**: UUID of your Voice+ journey/script
    4. **Conversation ID**: Passed from the active voice bot
    
    ## Authentication
    
    ### Conversation API
    - **Header**: `nlx-api-key` with your channel's API key
    - **Obtain from**: Channel setup instructions in your deployment
    
    ### Voice+ Script API
    - **Headers**: `x-api-key` (Voice+ API key) + `x-nlx-id` (workspace ID)
    - **Obtain from**: Voice+ journey/script configuration
    
    ## SDK Integration
    
    **Recommended**: Use the official NLX SDKs for seamless integration:
    - **JavaScript/TypeScript**: `@nlxai/core` - Full conversation management
    - **Voice+**: `@nlxai/touchpoint-ui` - Bidirectional voice interactions
    - **Voice+ Script**: `@nlxai/voice-plus-core` - Multimodal journey tracking
    
    ### Quick SDK Setup
    
    #### Conversation API
    ```typescript
    import { createConversation } from "@nlxai/core";
    
    const config = {
      applicationUrl: "https://apps.nlx.ai/c/{deploymentKey}/{channelKey}",
      headers: { "nlx-api-key": "your_api_key_here" },
      languageCode: "en-US",
      userId: "user_12345"
    };
    
    const conversation = createConversation(config);
    conversation.sendText("Hello, I need help with my account");
    ```
    
    #### Voice+ Script API
    ```typescript
    import { create } from "@nlxai/voice-plus-core";
    
    const client = create({
      apiKey: "your_voice_plus_api_key",
      workspaceId: "your_workspace_id",
      scriptId: "your_script_uuid",
      conversationId: "conversation_from_voice_bot",
      languageCode: "en-US"
    });
    
    client.sendStep("step_uuid", { selectedOption: "A" });
    ```
    
    ### Conversation SDK API Methods
    | SDK Method | API Request | Description |
    |------------|-------------|-------------|
    | `sendText(text, context)` | `unstructured` | Natural language text for NLP processing |
    | `sendChoice(choiceId, context)` | `structured.choiceId` | User selection from bot choices |
    | `sendFlow(flowId, context)` | `structured.flowId` | Trigger specific conversation flow |
    | `sendSlots(slots, context)` | `structured.slots` | Provide slot values directly |
    | `sendStructured(request, context)` | `structured` | Complex requests with multiple parameters |
    | `sendContext(context)` | `/context` endpoint | Voice+ bidirectional context |
    
    ### Voice+ Script API Methods
    | SDK Method | API Endpoint | Description |
    |------------|-------------|-------------|
    | `sendStep(stepId, context)` | `/v1/track` | Track progress through multimodal voice journeys |
    
    ### SDK Response Processing
    
    The SDK automatically processes API responses into structured objects:
    - **Messages**: Text content and user choices
    - **Modalities**: Rich media components (videos, images, custom components)
    - **Context**: Variables returned when enabled on flow nodes
    - **Metadata**: Intent detection, escalation flags, knowledge base sources

  contact:
    name: NLX Support
    url: https://docs.nlx.ai
  license:
    name: Proprietary
    url: https://nlx.ai/terms

servers:
  - url: https://apps.nlx.ai
    description: Production - Main Conversation API
  - url: https://mm.nlx.ai
    description: Production - Voice+ Script API

security:
  - ApiKeyAuth: []

paths:
  /c/{deploymentKey}/{channelKey}:
    post:
      summary: Send message to conversational AI
      description: |
        Main endpoint for sending messages to your conversational application. 
        Supports both unstructured text input and structured intent/choice requests.
        
        **Channel Key Format**: May include language code (e.g., `mychannel-en-US`)
        
        **Request Types**:
        - **Unstructured**: Send natural language text for NLP processing
        - **Structured**: Send explicit intents, choices, or slot values
        
        **Response**: Returns bot messages, choices, modalities, and metadata
        
      operationId: sendMessage
      tags:
        - Conversation API
      parameters:
        - name: deploymentKey
          in: path
          required: true
          schema:
            type: string
          description: The unique deployment identifier
          example: "my-deployment-123"
        - name: channelKey
          in: path
          required: true
          schema:
            type: string
          description: Channel identifier, optionally with language suffix
          example: "api-channel-en-US"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ConversationRequest"
            examples:
              sdk_send_text_basic:
                summary: "SDK sendText() - Basic text message"
                description: "Equivalent to conversationHandler.sendText('Hello, I need help with my account')"
                value:
                  request:
                    unstructured:
                      text: "Hello, I need help with my account"
                  userId: "user_12345"
                  conversationId: "conv_abcd1234"
              
              sdk_send_text_with_context:
                summary: "SDK sendText() - With context"
                description: "Equivalent to conversationHandler.sendText('What\\'s my balance?', { userTier: 'premium' })"
                value:
                  request:
                    unstructured:
                      text: "What's my current balance?"
                  userId: "user_12345"
                  conversationId: "conv_abcd1234"
                  context:
                    userTier: "premium"
                    currentPage: "/account/dashboard"
                    sessionStart: "2024-01-15T10:30:00Z"
              
              sdk_send_choice_basic:
                summary: "SDK sendChoice() - User selects option"
                description: "Equivalent to conversationHandler.sendChoice('choice_savings_123')"
                value:
                  request:
                    structured:
                      choiceId: "choice_savings_123"
                  userId: "user_12345"
                  conversationId: "conv_abcd1234"
              
              sdk_send_choice_with_metadata:
                summary: "SDK sendChoice() - With node metadata"
                description: "Equivalent to sendChoice(choiceId, context, { nodeId, intentId })"
                value:
                  request:
                    structured:
                      choiceId: "choice_transfer_money"
                      nodeId: "node_service_selection"
                  userId: "user_12345"
                  conversationId: "conv_abcd1234"
                  context:
                    previousAction: "account_balance_check"
              
              sdk_send_structured_flow:
                summary: "SDK sendFlow() - Trigger flow"
                description: "Equivalent to conversationHandler.sendFlow('CheckBalance')"
                value:
                  request:
                    structured:
                      flowId: "CheckBalance"
                  userId: "user_12345"
                  conversationId: "conv_abcd1234"
              
              sdk_send_slots:
                summary: "SDK sendSlots() - Send slot values"
                description: "Equivalent to conversationHandler.sendSlots({ AccountType: 'savings', TransactionLimit: 5000 })"
                value:
                  request:
                    structured:
                      slots:
                        - slotId: "AccountType"
                          value: "savings"
                        - slotId: "TransactionLimit"
                          value: 5000
                  userId: "user_12345"
                  conversationId: "conv_abcd1234"
              
              sdk_send_structured_complex:
                summary: "SDK sendStructured() - Complex request"
                description: "Complete structured request with flow, slots, and context"
                value:
                  request:
                    structured:
                      flowId: "TransferMoney"
                      slots:
                        - slotId: "FromAccount"
                          value: "savings"
                        - slotId: "ToAccount"
                          value: "checking"
                        - slotId: "Amount"
                          value: 250.00
                      utterance: "Transfer $250 from savings to checking"
                  userId: "user_12345"
                  conversationId: "conv_abcd1234"
                  context:
                    transferType: "internal"
                    verifiedIdentity: true
              
              sdk_file_upload:
                summary: "SDK file upload - Document processing"
                description: "Send structured request with uploaded documents"
                value:
                  request:
                    structured:
                      flowId: "ProcessDocument"
                      uploadIds: ["upload_doc_789", "upload_img_101"]
                      slots:
                        - slotId: "DocumentType"
                          value: "bank_statement"
                  userId: "user_12345"
                  conversationId: "conv_abcd1234"
                  context:
                    uploadedAt: "2024-01-15T10:30:00Z"
                    fileCount: 2
      responses:
        "200":
          description: Successful conversation response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ConversationResponse"
              examples:
                sdk_expected_text_response:
                  summary: "Response SDK processes - Text message"
                  description: "Structure the SDK's ApplicationResponse expects and processes"
                  value:
                    conversationId: "conv_abcd1234"
                    expirationTimestamp: "2024-01-15T11:30:00Z"
                    messages:
                      - messageId: "msg_001"
                        text: "I found your account information. Your current balance is $2,347.50."
                        choices: []
                        metadata:
                          intentId: "CheckBalance"
                    metadata:
                      intentId: "CheckBalance"
                      isGenerative: false
                      hasPendingDataRequest: false
                      escalation: false
                      frustration: false
                      incomprehension: false
                      uploadUrls: []
                
                sdk_expected_choices_response:
                  summary: "Response SDK processes - With choices"
                  description: "Response structure for choice interactions as processed by ConversationHandler"
                  value:
                    conversationId: "conv_abcd1234"
                    expirationTimestamp: "2024-01-15T11:30:00Z"
                    messages:
                      - messageId: "msg_002"
                        text: "What would you like to do with your account?"
                        choices:
                          - choiceId: "choice_balance"
                            choiceText: "Check Balance"
                          - choiceId: "choice_transfer"
                            choiceText: "Transfer Money"
                            choicePayload: "priority_action"
                          - choiceId: "choice_history"
                            choiceText: "View History"
                        choicesMetadata:
                          source: "slot"
                          slotId: "AccountAction"
                          slotType: "AccountAction"
                          transient: false
                          resolutionType: "static"
                          elicitationStyle: "button"
                          associatedSlotIds: []
                          intentId: "MainMenu"
                    metadata:
                      intentId: "MainMenu"
                      isGenerative: false
                      escalation: false
                      hasPendingDataRequest: false
                
                sdk_expected_modalities_response:
                  summary: "Response SDK processes - With modalities"
                  description: "Modalities as processed by touchpoint-ui custom modality components"
                  value:
                    conversationId: "conv_abcd1234"
                    expirationTimestamp: "2024-01-15T11:30:00Z"
                    messages:
                      - messageId: "msg_003"
                        text: "Here's your account summary and helpful resources:"
                    modalities:
                      AccountCard:
                        accountType: "Savings"
                        balance: "$2,347.50"
                        lastTransaction: "2024-01-14"
                        cardColor: "#1a73e8"
                        clickable: true
                      HelpVideo:
                        title: "How to Transfer Money"
                        url: "https://help.mybank.com/transfers.mp4"
                        duration: 90
                        thumbnail: "https://help.mybank.com/transfers-thumb.jpg"
                        autoplay: false
                      DocumentUpload:
                        acceptedTypes: [".pdf", ".jpg", ".png"]
                        maxFileSize: "10MB"
                        uploadUrl: "https://api.mybank.com/upload"
                    metadata:
                      intentId: "AccountSummary"
                      isGenerative: false
                      uploadUrls: 
                        - "https://s3.amazonaws.com/uploads/user12345/slot1?signature=..."
                
                sdk_knowledge_base_response:
                  summary: "Response SDK processes - Knowledge base with sources"
                  description: "Knowledge base response with source citations as processed by SDK"
                  value:
                    conversationId: "conv_abcd1234"
                    expirationTimestamp: "2024-01-15T11:30:00Z"
                    messages:
                      - messageId: "msg_004"
                        text: "Based on our help documentation, here's how to transfer money: First, log into your account and navigate to the Transfer Money section..."
                        metadata:
                          sources:
                            - fileName: "transfer-guide.pdf"
                              pageNumber: 3
                              content: "To transfer money between accounts, follow these steps: 1) Select source account 2) Select destination account 3) Enter amount..."
                              metadata:
                                documentType: "help-guide"
                                lastUpdated: "2024-01-10"
                                category: "transfers"
                              presignedUrl: "https://s3.amazonaws.com/docs/transfer-guide.pdf?signature=..."
                            - fileName: "faq.pdf"
                              pageNumber: 15
                              content: "Q: What are the daily transfer limits? A: Standard accounts have a $5,000 daily limit, Premium accounts have $25,000..."
                              metadata:
                                documentType: "faq"
                                section: "limits"
                    metadata:
                      intentId: "TransferHelp"
                      isGenerative: true
                      sources: 
                        - fileName: "transfer-guide.pdf"
                          pageNumber: 3
                          content: "To transfer money between accounts, follow these steps..."
                      feedbackUrl: "https://api.mybank.com/feedback/msg_004"
                
                sdk_context_response:
                  summary: "Response SDK processes - With context return"
                  description: "Bot sends back context when 'Send context' is enabled on flow node"
                  value:
                    conversationId: "conv_abcd1234"
                    expirationTimestamp: "2024-01-15T11:30:00Z"
                    messages:
                      - messageId: "msg_005"
                        text: "I've updated your transfer preferences successfully."
                    context:
                      botId: "bot_banking_assistant"
                      channelId: "channel_web_chat"
                      languageCode: "en-US"
                      userTier: "premium"
                      lastAction: "update_transfer_preferences"
                      transferLimit: 5000
                      preferredAccount: "savings"
                      notificationsEnabled: true
                    metadata:
                      intentId: "UpdateTransferPreferences"
                      isGenerative: false
                
                sdk_polling_response:
                  summary: "Response SDK processes - Pending data request"
                  description: "Response that triggers SDK polling for additional data"
                  value:
                    conversationId: "conv_abcd1234"
                    expirationTimestamp: "2024-01-15T11:30:00Z"
                    messages:
                      - messageId: "msg_006"
                        text: "I'm processing your transfer request. This may take a few moments..."
                    metadata:
                      intentId: "ProcessTransfer"
                      isGenerative: false
                      hasPendingDataRequest: true
                      escalation: false
        
        "400":
          description: Bad Request - Invalid request format or missing required fields
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              examples:
                missing_request_body:
                  summary: "Missing request body"
                  description: "SDK error when request object is missing"
                  value:
                    error: "BAD_REQUEST"
                    message: "Request body is required"
                    details:
                      errorCode: "MISSING_REQUEST_BODY"
                
                invalid_choice_id:
                  summary: "Invalid choice ID"
                  description: "SDK error when sendChoice() uses invalid choiceId"
                  value:
                    error: "BAD_REQUEST"
                    message: "Invalid choiceId. Choice not found in current conversation context."
                    details:
                      errorCode: "INVALID_CHOICE_ID"
                      providedChoiceId: "choice_invalid_123"
                      availableChoices: ["choice_balance", "choice_transfer", "choice_history"]
                
                conversation_expired:
                  summary: "Conversation expired"
                  description: "SDK error when conversation has expired"
                  value:
                    error: "BAD_REQUEST"
                    message: "Conversation has expired. Please start a new conversation."
                    details:
                      errorCode: "CONVERSATION_EXPIRED"
                      expiredAt: "2024-01-15T10:30:00Z"
                      conversationId: "conv_abcd1234"
        
        "401":
          description: Unauthorized - Invalid or missing API key
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              examples:
                missing_api_key:
                  summary: "Missing API key"
                  description: "SDK error when nlx-api-key header is missing"
                  value:
                    error: "UNAUTHORIZED"
                    message: "Missing required nlx-api-key header"
                    details:
                      errorCode: "MISSING_API_KEY"
                      helpUrl: "https://docs.studio.nlx.ai/channels/api#setup"
                
                invalid_api_key:
                  summary: "Invalid API key"
                  description: "SDK error when API key is malformed or revoked"
                  value:
                    error: "UNAUTHORIZED"
                    message: "Invalid API key. Check your channel configuration."
                    details:
                      errorCode: "INVALID_API_KEY"
                      keyPrefix: "sk_..."
                      helpUrl: "https://docs.studio.nlx.ai/channels/api#setup"
        
        "403":
          description: Forbidden - Valid API key but access denied
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              examples:
                quota_exceeded:
                  summary: "Quota exceeded"
                  description: "SDK error when conversation quota is exceeded"
                  value:
                    error: "FORBIDDEN"
                    message: "Monthly conversation quota exceeded. Please upgrade your plan."
                    details:
                      errorCode: "QUOTA_EXCEEDED"
                      currentUsage: 10000
                      limit: 10000
                      resetDate: "2024-02-01T00:00:00Z"
                
                channel_disabled:
                  summary: "Channel disabled"
                  description: "SDK error when API channel is disabled"
                  value:
                    error: "FORBIDDEN"
                    message: "API channel is disabled for this deployment"
                    details:
                      errorCode: "CHANNEL_DISABLED"
                      channelId: "channel_api_123"
        
        "429":
          description: Too Many Requests - Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              examples:
                rate_limit_exceeded:
                  summary: "Rate limit exceeded"
                  description: "SDK error when API rate limit is exceeded"
                  value:
                    error: "TOO_MANY_REQUESTS"
                    message: "Rate limit exceeded. Maximum 100 requests per minute."
                    details:
                      errorCode: "RATE_LIMIT_EXCEEDED"
                      limit: 100
                      window: "1 minute"
                      retryAfter: 30
                      resetTime: "2024-01-15T10:31:00Z"

  /c/{deploymentKey}/{channelKey}/context:
    post:
      summary: Send Voice+ context information
      description: |
        Send contextual information for Voice+ multimodal conversations.
        This endpoint allows you to provide structured context about web page elements,
        available actions, form fields, and navigation destinations.
        
        **Use Cases**:
        - Provide page context for voice-enabled web applications
        - Define available actions the AI can perform
        - Specify form fields that can be filled
        - Set navigation destinations
        
        **Security**: Requires valid API key and conversation context
      operationId: sendContext
      tags:
        - Voice+ Context API
      parameters:
        - name: deploymentKey
          in: path
          required: true
          schema:
            type: string
          description: The unique deployment identifier
        - name: channelKey
          in: path
          required: true
          schema:
            type: string
          description: Channel identifier
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/VoicePlusContextRequest"
            examples:
              sdk_banking_transfer_context:
                summary: "SDK Voice+ - Banking transfer form"
                description: "Real context sent by touchpoint-ui automatic context gathering for banking transfer"
                value:
                  conversationId: "conv_voice_bank123"
                  nonce: "nonce_auto_generated"
                  context:
                    "nlx:vpContext":
                      uri: "https://mybank.com/transfer"
                      fields:
                        - id: "fromAccount"
                          name: "From Account"
                          type: "select"
                          description: "Source account for the money transfer"
                          value: "savings_account_001"
                        - id: "toAccount"
                          name: "To Account"
                          type: "select"
                          description: "Destination account for the money transfer"
                          value: ""
                        - id: "amount"
                          name: "Transfer Amount"
                          type: "number"
                          description: "Amount to transfer in USD (minimum $0.01, maximum $5000.00)"
                          placeholder: "Enter amount"
                          value: ""
                        - id: "memo"
                          name: "Transfer Memo"
                          type: "text"
                          description: "Optional memo for the transfer"
                          placeholder: "Optional memo"
                          value: ""
                      actions:
                        - action: "submitTransfer"
                          description: "Execute the money transfer with current form data and user verification"
                          schema:
                            type: "object"
                            required: ["fromAccount", "toAccount", "amount"]
                            properties:
                              fromAccount: 
                                type: "string"
                                description: "Source account identifier"
                              toAccount: 
                                type: "string"
                                description: "Destination account identifier"
                              amount: 
                                type: "number"
                                minimum: 0.01
                                maximum: 5000.00
                                description: "Transfer amount in USD"
                              memo:
                                type: "string"
                                maxLength: 100
                        - action: "validateTransfer"
                          description: "Validate transfer details without executing"
                          schema:
                            type: "object"
                            properties:
                              fromAccount: { type: "string" }
                              toAccount: { type: "string" }
                              amount: { type: "number" }
                        - action: "clearForm"
                          description: "Reset all form fields to default values"
                      destinations:
                        - "/account/history"
                        - "/account/dashboard"
                        - "/help/transfers"
                        - "/account/settings"
              
              sdk_ecommerce_checkout_context:
                summary: "SDK Voice+ - E-commerce checkout"
                description: "Voice+ context for e-commerce checkout flow with form validation"
                value:
                  conversationId: "conv_voice_shop456"
                  nonce: "nonce_checkout_789"
                  context:
                    "nlx:vpContext":
                      uri: "https://mystore.com/checkout"
                      fields:
                        - id: "shippingAddress"
                          name: "Shipping Address"
                          type: "textarea"
                          description: "Complete shipping address including street, city, state, zip"
                          placeholder: "Enter full shipping address"
                          value: ""
                        - id: "paymentMethod"
                          name: "Payment Method"
                          type: "select"
                          description: "Selected payment method for the order"
                          value: "credit_card"
                        - id: "promoCode"
                          name: "Promo Code"
                          type: "text"
                          description: "Optional promotional discount code"
                          placeholder: "Enter promo code"
                          value: ""
                        - id: "expeditedShipping"
                          name: "Expedited Shipping"
                          type: "checkbox"
                          description: "Add expedited shipping for additional $15.99"
                          value: false
                      actions:
                        - action: "applyPromoCode"
                          description: "Apply promotional code and recalculate order total"
                          schema:
                            type: "object"
                            properties:
                              promoCode:
                                type: "string"
                                pattern: "^[A-Z0-9]{4,12}$"
                                description: "Promotional code (4-12 uppercase alphanumeric characters)"
                        - action: "calculateShipping"
                          description: "Calculate shipping cost based on address and speed"
                          schema:
                            type: "object"
                            properties:
                              address: { type: "string" }
                              expedited: { type: "boolean" }
                        - action: "placeOrder"
                          description: "Complete the order with current details"
                          schema:
                            type: "object"
                            required: ["shippingAddress", "paymentMethod"]
                            properties:
                              shippingAddress: { type: "string", minLength: 10 }
                              paymentMethod: { type: "string" }
                              promoCode: { type: "string" }
                              expedited: { type: "boolean" }
                      destinations:
                        - "/cart"
                        - "/account/orders"
                        - "/help/checkout"
                        - "/products"
              
              sdk_dashboard_navigation_context:
                summary: "SDK Voice+ - Dashboard navigation"
                description: "Context for complex dashboard with multiple sections and custom commands"
                value:
                  conversationId: "conv_voice_dash789"
                  nonce: "nonce_nav_012"
                  context:
                    "nlx:vpContext":
                      uri: "https://analytics.myapp.com/dashboard"
                      fields:
                        - id: "dateRange"
                          name: "Date Range Filter"
                          type: "select"
                          description: "Time period for analytics data"
                          value: "last_30_days"
                        - id: "searchQuery"
                          name: "Search Query"
                          type: "text"
                          description: "Search across all dashboard data"
                          placeholder: "Search transactions, customers, etc."
                          value: ""
                      actions:
                        - action: "navigateToSection"
                          description: "Navigate to a specific section of the analytics dashboard"
                          schema:
                            type: "object"
                            properties:
                              section:
                                type: "string"
                                enum: ["overview", "analytics", "reports", "customers", "transactions", "settings"]
                                description: "Target dashboard section"
                        - action: "generateReport"
                          description: "Generate a custom report with specified parameters"
                          schema:
                            type: "object"
                            properties:
                              reportType:
                                type: "string"
                                enum: ["sales", "customers", "transactions", "performance"]
                              dateRange: { type: "string" }
                              format: 
                                type: "string"
                                enum: ["pdf", "csv", "json"]
                                default: "pdf"
                        - action: "exportData"
                          description: "Export filtered dashboard data"
                          schema:
                            type: "object"
                            properties:
                              dataType: 
                                type: "string"
                                enum: ["transactions", "customers", "products"]
                              format: { type: "string", enum: ["csv", "json", "xlsx"] }
                              filters: { type: "object" }
                        - action: "searchDashboard"
                          description: "Perform search across all dashboard sections"
                          schema:
                            type: "object"
                            properties:
                              query: 
                                type: "string"
                                minLength: 2
                                description: "Search query string"
                              scope:
                                type: "array"
                                items:
                                  type: "string"
                                  enum: ["transactions", "customers", "products", "reports"]
                      destinations:
                        - "/dashboard/overview"
                        - "/dashboard/analytics"
                        - "/dashboard/reports"
                        - "/dashboard/customers"
                        - "/dashboard/transactions"
                        - "/dashboard/settings"
                        - "/help/dashboard"
                        - "/account/profile"
      responses:
        "200":
          description: Context successfully received and processed
          content:
            application/json:
              schema:
                type: object
                example: {}
        
        "400":
          description: Bad Request - Invalid context format or missing required fields
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error: "BAD_REQUEST"
                message: "Invalid Voice+ context format"
        
        "403":
          description: Forbidden - Invalid API key or unauthorized context submission
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error: "FORBIDDEN"
                message: "Unauthorized context submission"

  /v1/track:
    post:
      summary: Voice+ step tracking
      description: |
        Track user progress through Voice+ multimodal journeys by sending step transitions.
        This endpoint is part of the Voice+ Script API (mm.nlx.ai) and is separate from the main conversation API.
        
        **SDK Integration**: Use `@nlxai/voice-plus-core` for seamless integration:
        ```typescript
        import { create } from "@nlxai/voice-plus-core";
        
        const client = create({
          apiKey: "your_voice_plus_api_key",
          workspaceId: "your_workspace_id", 
          scriptId: "script_uuid",
          conversationId: "conversation_id_from_voice_bot",
          languageCode: "en-US"
        });
        
        client.sendStep("step_uuid", { selectedSeat: "4A" });
        ```
        
        **Use Cases**:
        - Track user progress through multimodal voice experiences
        - Send contextual data back to voice applications
        - Coordinate between web interfaces and voice interactions
        - Analytics and journey optimization
        
        **Authentication**: Uses Voice+ API key authentication with `x-api-key` and `x-nlx-id` headers
      operationId: trackVoice+Step
      tags:
        - Voice+ Script API
      servers:
        - url: https://mm.nlx.ai
          description: Production - Voice+ Script API
        - url: https://dev.mm.nlx.ai
          description: Development - Voice+ Script API
      security:
        - VoicePlusAuth: []
      parameters:
        - name: x-nlx-id
          in: header
          required: true
          schema:
            type: string
          description: |
            Workspace identifier required for Voice+ API authentication.
            
            **SDK Setup**: Configured as `workspaceId` in client creation
          example: "workspace_abc123"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/VoicePlusStepRequest"
            examples:
              sdk_send_step_basic:
                summary: "SDK sendStep() - Basic step tracking"
                description: "Equivalent to client.sendStep('step-uuid-123')"
                value:
                  stepId: "550e8400-e29b-41d4-a716-446655440000"
                  conversationId: "conv_voice_abc123"
                  journeyId: "journey_uuid_def456"
                  languageCode: "en-US"
              
              sdk_send_step_with_context:
                summary: "SDK sendStep() - With context data"
                description: "Equivalent to client.sendStep(stepInfo, { selectedSeat: '4A', preferences: {...} })"
                value:
                  stepId: "550e8400-e29b-41d4-a716-446655440001"
                  conversationId: "conv_voice_abc123"
                  journeyId: "journey_uuid_def456"
                  languageCode: "en-US"
                  context:
                    selectedSeat: "4A"
                    flightNumber: "UA1234"
                    preferences:
                      mealType: "vegetarian"
                      specialAssistance: false
                  stepTriggerDescription: "User selected seat 4A"
              
              sdk_ecommerce_step:
                summary: "SDK sendStep() - E-commerce journey"
                description: "Step tracking for e-commerce multimodal experience"
                value:
                  stepId: "550e8400-e29b-41d4-a716-446655440002"
                  conversationId: "conv_shop_xyz789"
                  journeyId: "ecommerce_journey_ghi012"
                  languageCode: "en-US"
                  context:
                    productId: "PROD_12345"
                    productName: "Wireless Headphones"
                    price: 149.99
                    cartTotal: 149.99
                    shippingMethod: "express"
                    promotionCode: "SAVE20"
                  stepTriggerDescription: "Added product to cart via voice command"
              
              sdk_banking_step:
                summary: "SDK sendStep() - Banking journey"
                description: "Step tracking for banking/financial multimodal experience"
                value:
                  stepId: "550e8400-e29b-41d4-a716-446655440003"
                  conversationId: "conv_bank_mno345"
                  journeyId: "banking_transfer_pqr678"
                  languageCode: "en-US"
                  context:
                    transferAmount: 500.00
                    fromAccount: "checking_001"
                    toAccount: "savings_002"
                    transferType: "internal"
                    authenticationMethod: "voice_biometric"
                    riskScore: 0.1
                  stepTriggerDescription: "User confirmed transfer details via voice"
              
              sdk_step_object_format:
                summary: "SDK sendStep() - Step object format"
                description: "Using step object instead of string for additional metadata"
                value:
                  stepId: "550e8400-e29b-41d4-a716-446655440004"
                  conversationId: "conv_support_stu901"
                  journeyId: "support_journey_vwx234"
                  languageCode: "en-US"
                  stepTriggerDescription: "Customer escalated to human agent after voice interaction failed"
                  context:
                    issue: "billing_dispute"
                    priority: "high"
                    attempts: 3
                    lastIntentConfidence: 0.2
                    escalationReason: "low_confidence_multiple_attempts"
      responses:
        "200":
          description: Step successfully tracked
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/VoicePlusStepResponse"
              examples:
                successful_tracking:
                  summary: "Successful step tracking"
                  description: "Step was successfully recorded and processed"
                  value:
                    success: true
                    stepId: "550e8400-e29b-41d4-a716-446655440000"
                    timestamp: "2024-01-15T10:30:00.000Z"
                    conversationId: "conv_voice_abc123"
                    journeyId: "journey_uuid_def456"
        
        "400":
          description: Bad Request - Invalid step data or format
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              examples:
                invalid_step_id:
                  summary: "Invalid step ID format"
                  description: "Step ID must be a valid UUID format"
                  value:
                    error: "BAD_REQUEST"
                    message: "Invalid stepId. It should be formatted as a UUID."
                    details:
                      errorCode: "INVALID_STEP_ID"
                      providedStepId: "not-a-uuid"
                      expectedFormat: "UUID v4 (e.g., 550e8400-e29b-41d4-a716-446655440000)"
                
                missing_required_fields:
                  summary: "Missing required fields"
                  description: "Required fields for step tracking are missing"
                  value:
                    error: "BAD_REQUEST"
                    message: "Missing required fields: conversationId, journeyId"
                    details:
                      errorCode: "MISSING_REQUIRED_FIELDS"
                      missingFields: ["conversationId", "journeyId"]
                      requiredFields: ["stepId", "conversationId", "journeyId", "languageCode"]
        
        "401":
          description: Unauthorized - Invalid or missing Voice+ API credentials
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              examples:
                missing_api_key:
                  summary: "Missing Voice+ API key"
                  description: "x-api-key header is required for Voice+ API"
                  value:
                    error: "UNAUTHORIZED"
                    message: "Missing required x-api-key header"
                    details:
                      errorCode: "MISSING_VOICE_PLUS_API_KEY"
                      requiredHeaders: ["x-api-key", "x-nlx-id"]
                
                invalid_workspace:
                  summary: "Invalid workspace ID"
                  description: "x-nlx-id header contains invalid workspace identifier"
                  value:
                    error: "UNAUTHORIZED"
                    message: "Invalid workspace ID in x-nlx-id header"
                    details:
                      errorCode: "INVALID_WORKSPACE_ID"
                      providedWorkspaceId: "invalid_workspace"
        
        "403":
          description: Forbidden - Valid credentials but access denied to journey/script
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              examples:
                journey_access_denied:
                  summary: "Journey access denied"
                  description: "API key does not have access to the specified journey/script"
                  value:
                    error: "FORBIDDEN"
                    message: "Access denied to journey/script. Check your API key permissions."
                    details:
                      errorCode: "JOURNEY_ACCESS_DENIED"
                      journeyId: "journey_uuid_def456"
                      workspaceId: "workspace_123"
        
        "429":
          description: Too Many Requests - Voice+ API rate limit exceeded
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              examples:
                rate_limit_voice_plus:
                  summary: "Voice+ rate limit exceeded"
                  description: "Too many step tracking requests in time window"
                  value:
                    error: "TOO_MANY_REQUESTS"
                    message: "Voice+ API rate limit exceeded. Maximum 1000 steps per minute."
                    details:
                      errorCode: "VOICE_PLUS_RATE_LIMIT_EXCEEDED"
                      limit: 1000
                      window: "1 minute"
                      retryAfter: 60

components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: nlx-api-key
      description: |
        API key authentication required for all conversational endpoints.
        Obtain your API key from the channel setup instructions in your deployment.
    
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: |
        JWT Bearer token authentication for NLP endpoints.
        Token should include customer ID and user permissions.
    
    VoicePlusAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: |
        Voice+ Multimodal API authentication requires two headers:
        - `x-api-key`: Voice+ API key (different from conversation API key)
        - `x-nlx-id`: Workspace identifier
        
        **SDK Configuration**: These are automatically handled when using `@nlxai/voice-plus-core`
        
        Obtain these credentials from your Voice+ journey/script configuration.

  schemas:
    ConversationRequest:
      type: object
      required:
        - request
      properties:
        request:
          oneOf:
            - $ref: "#/components/schemas/UnstructuredRequest"
            - $ref: "#/components/schemas/StructuredRequest"
          description: |
            The request payload - either unstructured text or structured intent/choice data.
            Use unstructured for natural language input, structured for explicit intents/choices.
        
        conversationId:
          type: string
          nullable: true
          description: |
            Unique identifier for the conversation session. If not provided, a new conversation will be created.
            Use the same ID across requests to maintain conversation context.
          example: "conv_abc123def456"
        
        userId:
          type: string
          description: |
            Unique identifier for the user. Used for personalization and conversation tracking.
            Can be overridden by context.nlx_userId if provided.
          example: "user_789xyz"
        
        context:
          type: object
          additionalProperties: true
          description: |
            Additional context attributes to provide to the bot. These can be used for:
            - Personalization (user tier, preferences)
            - Session state (current page, form data) 
            - Business logic (product catalog, user permissions)
            
            Special context variables:
            - nlx_userId: Overrides the userId field
            - originPage: Tracks where the conversation originated
          example:
            originPage: "account-dashboard"
            userTier: "premium"
            currentBalance: 1250.00
        
        environment:
          type: string
          enum: [development, production]
          description: Environment for request processing
          default: production

    UnstructuredRequest:
      type: object
      required:
        - unstructured
      properties:
        unstructured:
          type: object
          required:
            - text
          properties:
            text:
              type: string
              minLength: 1
              maxLength: 10000
              description: The user's natural language input text
              example: "Hello, I need help with my account"

    StructuredRequest:
      type: object
      required:
        - structured
      properties:
        structured:
          type: object
          properties:
            intentId:
              type: string
              description: |
                Explicit intent identifier to trigger. Use this when you want to 
                directly invoke a specific intent without NLP processing.
                
                **SDK Method**: `conversationHandler.sendIntent("IntentName")` (deprecated)
                **Preferred**: Use `flowId` instead
              example: "CheckAccountBalance"
              deprecated: true
            
            choiceId:
              type: string
              description: |
                Choice identifier from a previous bot response. Use this when the user
                selects an option from a choices array.
                
                **SDK Method**: `conversationHandler.sendChoice("choiceId", context, metadata)`
              example: "choice_123_yes"
            
            slots:
              type: array
              description: |
                Array of slot values to provide with the intent. Slots represent
                structured data extracted from user input or provided directly.
                
                **SDK Method**: `conversationHandler.sendSlots(slots, context)`
              items:
                type: object
                required:
                  - slotId
                  - value
                properties:
                  slotId:
                    type: string
                    description: The slot identifier
                    example: "AccountType"
                  value:
                    oneOf:
                      - type: string
                      - type: number
                      - type: boolean
                    description: The slot value
                    example: "savings"
                  topValues:
                    type: array
                    description: Alternative values if multiple options were detected
                    items:
                      oneOf:
                        - type: string
                        - type: number
                        - type: boolean
                  choicePayload:
                    type: string
                    description: Additional payload data associated with a choice selection
            
            uploadIds:
              type: array
              description: |
                Array of upload identifiers for files that have been uploaded.
                Use this to reference files in your structured request.
              items:
                type: string
              example: ["upload_abc123", "upload_def456"]
            
            utterance:
              type: string
              description: |
                Optional utterance text for structured requests. Can be used for
                logging or additional context processing.
              example: "Check my savings account balance"

    ConversationResponse:
      type: object
      required:
        - conversationId
        - messages
      properties:
        conversationId:
          type: string
          description: Unique identifier for the conversation session
          example: "conv_abc123def456"
        
        expirationTimestamp:
          type: string
          format: date-time
          description: |
            ISO 8601 timestamp when this conversation session will expire.
            After this time, conversation context may be lost.
          example: "2024-01-15T10:30:00Z"
        
        messages:
          type: array
          description: Array of response messages from the bot
          items:
            $ref: "#/components/schemas/ResponseMessage"
        
        modalities:
          type: object
          additionalProperties: true
          description: |
            Rich media modalities associated with the response. Each key is a modality type
            (e.g., "Video", "Image", "Audio") with corresponding configuration data.
            
            Modalities enable rich media experiences beyond text:
            - Videos with URL, title, duration
            - Images with URL, alt text, dimensions  
            - Audio files with URL, duration
            - Custom modalities with arbitrary data
          example:
            Video:
              title: "How to Reset Password"
              url: "https://example.com/video.mp4" 
              duration: 120
              resolution: 1080
            Image:
              alt: "Step-by-step guide"
              url: "https://example.com/guide.png"
              width: 800
              height: 600
        
        payload:
          type: string
          description: |
            Custom payload data from the conversation flow node. Can contain
            arbitrary string data for client-side processing.
            
            Common uses:
            - Trigger client-side animations (e.g., "confetti=true")
            - Pass configuration data (e.g., "theme=dark")
            - Send tracking codes (e.g., "event=purchase_complete")
          example: "confettiDisplay=true&celebrationSound=true"
        
        metadata:
          $ref: "#/components/schemas/ResponseMetadata"
        
        context:
          type: object
          additionalProperties: true
          description: |
            Context variables returned when "Send context" is enabled on a flow node.
            Includes both system context and custom attributes that have values.
            
            System context always includes:
            - botId: The bot identifier
            - channelId: The channel identifier  
            - languageCode: The language code used
            
            Custom context includes any context attributes with values.
          example:
            botId: "bot_123"
            channelId: "channel_456"
            languageCode: "en-US"
            userTier: "premium"
            lastAction: "balance_check"

    ResponseMessage:
      type: object
      required:
        - messageId
        - text
      properties:
        messageId:
          type: string
          description: Unique identifier for this message
          example: "msg_abc123"
        
        text:
          type: string
          description: The text content of the message
          example: "Hello! How can I help you today?"
        
        choices:
          type: array
          description: |
            Array of choices for user selection. When present, the user can select
            from these options instead of providing free-form text input.
          items:
            $ref: "#/components/schemas/MessageChoice"
        
        choicesMetadata:
          type: object
          description: |
            Metadata about the choices array, providing context about how choices
            should be handled and what they represent.
          properties:
            source:
              type: string
              enum: ["slot", "variable", "static"]
              description: The source of the choices (slot values, variables, or static)
              example: "slot"
            
            slotId:
              type: string
              description: The slot ID if choices come from a slot
              example: "AccountType"
            
            slotType:
              type: string
              description: The slot type if choices come from a slot
              example: "AccountType"
            
            transient:
              type: boolean
              description: Whether these choices are transient (one-time use)
              example: false
            
            resolutionType:
              type: string
              enum: ["static", "dynamic"]
              description: Whether choices are statically defined or dynamically generated
              example: "static"
            
            elicitationStyle:
              type: string
              enum: ["default", "button", "dropdown", "radio"]
              description: Suggested UI style for presenting choices
              example: "default"
            
            associatedSlotIds:
              type: array
              items:
                type: string
              description: Other slot IDs associated with this choice set
              example: []
            
            intentId:
              type: string
              description: The intent associated with these choices
              example: "SelectAccountType"
        
        metadata:
          type: object
          description: Additional metadata specific to this message
          additionalProperties: true
          properties:
            sources:
              type: array
              description: |
                Knowledge base sources used to generate this message.
                Present when the response is generated from knowledge base content.
              items:
                $ref: "#/components/schemas/KnowledgeBaseSource"

    MessageChoice:
      type: object
      required:
        - choiceId
        - choiceText
      properties:
        choiceId:
          type: string
          description: Unique identifier for this choice option
          example: "choice_savings_123"
        
        choiceText:
          type: string
          description: Display text for the choice
          example: "Savings Account"
        
        choicePayload:
          type: string
          description: |
            Optional payload data associated with this choice. Can be used by
            client applications for custom behavior or styling.
            
            Example uses:
            - Sorting hints ("isLastValue")
            - Styling classes ("primary-action")  
            - Additional data ("accountId=12345")
          example: "accountId=12345"

    KnowledgeBaseSource:
      type: object
      description: Source citation from knowledge base content
      properties:
        fileName:
          type: string
          description: Name of the source file
          example: "user-guide.pdf"
        
        pageNumber:
          type: integer
          description: Page number within the source document
          example: 15
        
        content:
          type: string
          description: Relevant content excerpt from the source
          example: "To reset your password, click the 'Forgot Password' link on the login page..."
        
        metadata:
          type: object
          additionalProperties: true
          description: Additional metadata about the source
          example:
            documentType: "user-guide"
            lastUpdated: "2024-01-01"
        
        presignedUrl:
          type: string
          format: uri
          description: Presigned URL to access the full source document
          example: "https://s3.example.com/docs/user-guide.pdf?signature=..."

    ResponseMetadata:
      type: object
      description: Metadata about the conversation response and processing
      properties:
        intentId:
          type: string
          description: The detected or triggered intent ID
          example: "CheckAccountBalance"
        
        escalation:
          type: boolean
          description: Whether escalation to human agent was triggered
          example: false
        
        frustration:
          type: boolean  
          description: Whether frustration was detected in user input
          example: false
        
        incomprehension:
          type: boolean
          description: Whether the bot failed to understand the user input
          example: false
        
        uploadUrls:
          type: array
          items:
            type: string
            format: uri
          description: Presigned URLs for file uploads
          example: ["https://s3.example.com/uploads/abc123?signature=..."]
        
        hasPendingDataRequest:
          type: boolean
          description: Whether there is a pending data request (e.g., API call)
          example: false
        
        isGenerative:
          type: boolean
          description: Whether the response used generative AI capabilities
          example: true
        
        feedbackUrl:
          type: string
          format: uri
          description: URL for submitting feedback about this response
          example: "https://api.example.com/feedback/msg_abc123"

    VoicePlusContextRequest:
      type: object
      required:
        - conversationId
        - context
      properties:
        conversationId:
          type: string
          description: The conversation ID for this Voice+ session
          example: "conv_voice123"
        
        nonce:
          type: string
          description: Security nonce for request validation (currently not enforced)
          example: "nonce_abc123"
        
        context:
          type: object
          required:
            - "nlx:vpContext"
          properties:
            "nlx:vpContext":
              $ref: "#/components/schemas/VoicePlusContext"

    VoicePlusContext:
      type: object
      description: |
        Voice+ context information describing the current web page state,
        available actions, form fields, and navigation options.
      properties:
        uri:
          type: string
          format: uri
          description: Current page URI
          example: "https://myapp.com/checkout"
        
        url:
          type: string
          format: uri
          description: Alternative URL field (deprecated, use uri)
          example: "https://myapp.com/checkout"
        
        fields:
          type: array
          description: |
            Form fields or interactive elements available on the current page.
            The voice AI can reference and interact with these fields.
          items:
            type: object
            required:
              - id
              - name  
              - type
            properties:
              id:
                type: string
                description: Unique field identifier
                example: "email"
              
              name:
                type: string
                description: Human-readable field name
                example: "Email Address"
              
              description:
                type: string
                description: Field description for AI context
                example: "Customer email address for order confirmation"
              
              type:
                type: string
                description: Field type (text, email, tel, number, etc.)
                example: "email"
              
              placeholder:
                type: string
                description: Placeholder text
                example: "Enter your email address"
              
              value:
                type: string
                description: Current field value
                example: ""
        
        actions:
          type: array
          description: |
            Available actions the voice AI can perform on the current page.
            Each action should have a clear description and optional schema.
          items:
            type: object
            required:
              - action
              - description
            properties:
              action:
                type: string
                description: Action identifier/name
                example: "submitOrder"
              
              description:
                type: string
                description: Human-readable action description
                example: "Submit the order with current form data"
              
              schema:
                type: object
                description: JSON schema describing action parameters
                example:
                  type: "object"
                  properties:
                    email:
                      type: "string"
                    phone:
                      type: "string"
        
        destinations:
          type: array
          items:
            type: string
          description: |
            Available navigation destinations from the current page.
            The voice AI can suggest or navigate to these locations.
          example:
            - "/confirmation"
            - "/cart"
            - "/account"

    DisambiguationRequest:
      type: object
      required:
        - utterance
        - customerId
        - botId
        - languageCode
      properties:
        utterance:
          type: string
          minLength: 1
          maxLength: 10000
          description: The user's input text to process
          example: "I want to check my account balance"
        
        customerId:
          type: string
          description: The customer ID (should be passed in token in future)
          example: "cust_abc123"
        
        botId:
          type: string
          description: The unique bot identifier
          example: "bot_def456"
        
        languageCode:
          type: string
          pattern: "^[a-z]{2}-[A-Z]{2}$"
          description: Language code in format 'xx-XX' (e.g., 'en-US', 'es-ES')
          example: "en-US"
        
        engineRegion:
          type: string
          description: The NLP engine region (engine-dependent, e.g., us-east-1, us-central1)
          example: "us-east-1"

    DisambiguationResponse:
      type: object
      description: NLP processing results with intent detection and slot extraction
      properties:
        intentId:
          type: string
          description: The identified intent ID
          example: "CheckAccountBalance"
        
        slots:
          type: array
          description: Extracted slot values from the utterance
          items:
            type: object
            properties:
              slotId:
                type: string
                description: The slot identifier
                example: "AccountType"
              
              value:
                type: string
                description: The extracted slot value
                example: "savings"
        
        sentiment:
          type: object
          description: Sentiment analysis results
          properties:
            label:
              type: string
              enum: ["positive", "negative", "neutral"]
              description: The sentiment classification
              example: "neutral"
            
            score:
              type: number
              minimum: -1
              maximum: 1
              description: Sentiment confidence score (-1 to 1)
              example: 0.1
        
        confidenceScore:
          type: number
          minimum: 0
          maximum: 1
          description: Confidence score for the intent classification
          example: 0.92
        
        boostIntentId:
          type: string
          description: Boosted intent ID if intent boosting was applied
          example: "CheckAccountBalance_Boosted"
        
        boostConfidenceScore:
          type: number
          minimum: 0
          maximum: 1
          description: Confidence score for the boosted intent
          example: 0.95
        
        nlpIntentId:
          type: string
          description: Raw NLP engine intent ID before any processing
          example: "account.balance.check"
        
        nlpConfidenceScore:
          type: number
          minimum: 0  
          maximum: 1
          description: Raw NLP engine confidence score
          example: 0.89
        
        boosted:
          type: boolean
          description: Whether intent boosting was applied
          example: false
        
        responseTime:
          type: number
          minimum: 0
          description: Processing time in milliseconds
          example: 145
        
        nlpLanguageCode:
          type: string
          description: Language code used by the NLP engine
          example: "en-US"

    ErrorResponse:
      type: object
      required:
        - error
        - message
      properties:
        error:
          type: string
          description: Error code identifier
          example: "BAD_REQUEST"
        
        message:
          type: string
          description: Human-readable error message
          example: "Request body is required"
        
        details:
          type: object
          additionalProperties: true
          description: Additional error details when available

    VoicePlusStepRequest:
      type: object
      required:
        - stepId
        - conversationId
        - journeyId
        - languageCode
      properties:
        stepId:
          type: string
          pattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"
          description: |
            UUID v4 identifier for the step being tracked. Must be a valid UUID format.
            
            **SDK Method**: `client.sendStep("stepId", context)` or `client.sendStep({ stepId, stepTriggerDescription })`
          example: "550e8400-e29b-41d4-a716-446655440000"
        
        conversationId:
          type: string
          description: |
            Unique identifier for the Voice+ conversation session.
            This ID links the step tracking to the active voice conversation.
            
            **SDK Setup**: Passed from voice bot or extracted from URL parameters
          example: "conv_voice_abc123"
        
        journeyId:
          type: string
          description: |
            UUID identifier for the Voice+ journey/script being executed.
            
            **SDK Setup**: Configured in client creation as `scriptId`
            **Note**: `journeyId` field is deprecated, use `scriptId` in SDK
          example: "journey_uuid_def456"
        
        languageCode:
          type: string
          pattern: "^[a-z]{2}-[A-Z]{2}$"
          description: |
            Language code for the Voice+ experience (format: 'xx-XX').
            Must match the language codes configured in the journey.
          example: "en-US"
        
        context:
          type: object
          additionalProperties: true
          description: |
            Optional context data to send with the step tracking.
            Can contain any structured data relevant to the current step.
            
            **Common Use Cases**:
            - User selections (seat numbers, product choices)
            - Form data (shipping info, payment details)
            - Business logic data (risk scores, preferences)
            - Analytics data (interaction times, error counts)
          example:
            selectedSeat: "4A"
            flightNumber: "UA1234"
            preferences:
              mealType: "vegetarian"
              specialAssistance: false
        
        stepTriggerDescription:
          type: string
          maxLength: 500
          description: |
            Optional human-readable description of what triggered this step transition.
            Useful for debugging, analytics, and journey optimization.
            
            **SDK Usage**: `client.sendStep({ stepId, stepTriggerDescription })`
          example: "User selected seat 4A via voice command"

    VoicePlusStepResponse:
      type: object
      description: Response confirming successful step tracking
      properties:
        success:
          type: boolean
          description: Whether the step was successfully tracked
          example: true
        
        stepId:
          type: string
          description: The step ID that was tracked
          example: "550e8400-e29b-41d4-a716-446655440000"
        
        timestamp:
          type: string
          format: date-time
          description: ISO 8601 timestamp when the step was recorded
          example: "2024-01-15T10:30:00.000Z"
        
        conversationId:
          type: string
          description: The conversation ID for this step tracking
          example: "conv_voice_abc123"
        
        journeyId:
          type: string
          description: The journey/script ID for this step
          example: "journey_uuid_def456"

tags:
  - name: Conversation API
    description: |
      Main conversational endpoints for sending messages and receiving bot responses.
      Supports both unstructured text input and structured intent/choice requests.
  
  - name: Voice+ Context API
    description: |
      Voice+ multimodal context endpoints for providing web page state,
      available actions, form fields, and navigation information.
  
  - name: Voice+ Script API
    description: |
      Voice+ Script API endpoints for tracking user progress through voice-enabled journeys.
      Separate API service (mm.nlx.ai) for coordinating multimodal experiences with step tracking,
      context sharing, and journey analytics. Use with `@nlxai/voice-plus-core` SDK.