{
  "components": {
    "schemas": {
      "cmd_server.AccountProfileUpdateRequest": {
        "properties": {
          "additional_contact": {
            "type": "string"
          },
          "address": {
            "type": "string"
          },
          "address_line1": {
            "type": "string"
          },
          "address_line2": {
            "type": "string"
          },
          "city": {
            "type": "string"
          },
          "company": {
            "type": "string"
          },
          "country": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "phone": {
            "type": "string"
          },
          "postal_code": {
            "type": "string"
          },
          "state_province": {
            "type": "string"
          }
        },
        "type": "object"
      },
      "cmd_server.CatalogProductCard": {
        "properties": {
          "available_crafts": {
            "items": {
              "additionalProperties": {
                "type": "string"
              },
              "type": "object"
            },
            "type": "array"
          },
          "available_materials": {
            "items": {
              "additionalProperties": {
                "type": "string"
              },
              "type": "object"
            },
            "type": "array"
          },
          "customization_options": {
            "example": [
              "logo engraving",
              "paper sleeve"
            ],
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "description": {
            "example": "Natural bamboo comb with engraved logo",
            "type": "string"
          },
          "detail_url": {
            "example": "https://www.vantrecomb.com/products/styles/bamboo-comb",
            "type": "string"
          },
          "finish": {
            "example": "natural polish",
            "type": "string"
          },
          "images": {
            "example": [
              "https://www.vantrecomb.com/images/bamboo-comb-1.jpg"
            ],
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "moq_note": {
            "example": "MOQ 5000 pcs",
            "type": "string"
          },
          "product_family": {
            "example": "combs",
            "type": "string"
          },
          "size": {
            "example": "180mm x 38mm",
            "type": "string"
          },
          "sku": {
            "example": "BC-001",
            "type": "string"
          },
          "style_id": {
            "example": "st_bamboo_comb",
            "type": "string"
          },
          "supports_oem": {
            "type": "boolean"
          },
          "three_d": {
            "$ref": "#/components/schemas/cmd_server.ThreeDInfo"
          },
          "title": {
            "example": "Bamboo Comb",
            "type": "string"
          }
        },
        "type": "object"
      },
      "cmd_server.CatalogProductDetail": {
        "properties": {
          "available_crafts": {
            "items": {
              "additionalProperties": {
                "type": "string"
              },
              "type": "object"
            },
            "type": "array"
          },
          "available_materials": {
            "items": {
              "additionalProperties": {
                "type": "string"
              },
              "type": "object"
            },
            "type": "array"
          },
          "available_scenarios": {
            "items": {
              "additionalProperties": {
                "type": "string"
              },
              "type": "object"
            },
            "type": "array"
          },
          "customization_options": {
            "example": [
              "logo engraving",
              "paper sleeve"
            ],
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "description": {
            "example": "Natural bamboo comb with engraved logo",
            "type": "string"
          },
          "detail_url": {
            "example": "https://www.vantrecomb.com/products/styles/bamboo-comb",
            "type": "string"
          },
          "finish": {
            "example": "natural polish",
            "type": "string"
          },
          "images": {
            "example": [
              "https://www.vantrecomb.com/images/bamboo-comb-1.jpg"
            ],
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "moq_note": {
            "example": "MOQ 5000 pcs",
            "type": "string"
          },
          "product_family": {
            "example": "combs",
            "type": "string"
          },
          "size": {
            "example": "180mm x 38mm",
            "type": "string"
          },
          "sku": {
            "example": "BC-001",
            "type": "string"
          },
          "style_id": {
            "example": "st_bamboo_comb",
            "type": "string"
          },
          "supports_oem": {
            "type": "boolean"
          },
          "three_d": {
            "$ref": "#/components/schemas/cmd_server.ThreeDInfo"
          },
          "title": {
            "example": "Bamboo Comb",
            "type": "string"
          }
        },
        "type": "object"
      },
      "cmd_server.CatalogProductDetailResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/cmd_server.CatalogProductDetail"
          },
          "request_id": {
            "type": "string"
          }
        },
        "type": "object"
      },
      "cmd_server.CatalogProductSearchMeta": {
        "properties": {
          "page": {
            "example": 1,
            "type": "integer"
          },
          "page_size": {
            "example": 20,
            "type": "integer"
          },
          "total": {
            "example": 42,
            "type": "integer"
          }
        },
        "type": "object"
      },
      "cmd_server.CatalogProductSearchResponse": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/cmd_server.CatalogProductCard"
            },
            "type": "array"
          },
          "meta": {
            "$ref": "#/components/schemas/cmd_server.CatalogProductSearchMeta"
          },
          "request_id": {
            "type": "string"
          }
        },
        "type": "object"
      },
      "cmd_server.ContactInfo": {
        "properties": {
          "address": {
            "type": "string"
          },
          "company": {
            "type": "string"
          },
          "country": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "phone": {
            "type": "string"
          }
        },
        "type": "object"
      },
      "cmd_server.CustomerResponse": {
        "properties": {
          "action": {
            "type": "string"
          },
          "contact": {
            "$ref": "#/components/schemas/cmd_server.ContactInfo"
          },
          "issue_type": {
            "description": "IssueType 问题类型（report_issue 追加的 issue_report 条目专用，可空）。\n关联对接文档：20260804-ERP-账户创建与标签关联对接-v1 契约 C。",
            "type": "string"
          },
          "note": {
            "type": "string"
          },
          "project_or_quote_no": {
            "description": "ProjectOrQuoteNo 客户填写的项目号/报价号（report_issue 追加的 issue_report 条目专用，可空）。",
            "type": "string"
          },
          "submitted_at": {
            "type": "string"
          },
          "type": {
            "type": "string"
          }
        },
        "type": "object"
      },
      "cmd_server.ProblemDetail": {
        "properties": {
          "code": {
            "example": "RFQ_MISSING_DESTINATION",
            "type": "string"
          },
          "detail": {
            "example": "Destination country is required.",
            "type": "string"
          },
          "missing_fields": {
            "example": [
              "destination_country"
            ],
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "retryable": {
            "example": true,
            "type": "boolean"
          },
          "status": {
            "example": 422,
            "type": "integer"
          },
          "title": {
            "example": "Required information is missing",
            "type": "string"
          },
          "trace_id": {
            "example": "tr_01JXYZ",
            "type": "string"
          },
          "type": {
            "example": "https://www.vantrecomb.com/problems/missing-field",
            "type": "string"
          }
        },
        "type": "object"
      },
      "cmd_server.RfqContact": {
        "properties": {
          "additional_contact": {
            "type": "string"
          },
          "company": {
            "example": "Acme Corp",
            "type": "string"
          },
          "country": {
            "example": "US",
            "type": "string"
          },
          "email": {
            "example": "buyer@example.com",
            "type": "string"
          },
          "name": {
            "example": "John Buyer",
            "type": "string"
          },
          "phone": {
            "example": "+1-555-0100",
            "type": "string"
          }
        },
        "required": [
          "company",
          "country",
          "email",
          "name"
        ],
        "type": "object"
      },
      "cmd_server.RfqGetResponse": {
        "properties": {
          "quote_record": {
            "$ref": "#/components/schemas/cmd_server.quoteRecordPublic"
          },
          "rfq_id": {
            "example": "rfq_xxx",
            "type": "string"
          },
          "status": {
            "example": "submitted_to_erp",
            "type": "string"
          },
          "submitted_at": {
            "example": "2026-07-14T12:00:00Z",
            "type": "string"
          }
        },
        "type": "object"
      },
      "cmd_server.RfqItem": {
        "properties": {
          "customization": {
            "additionalProperties": {},
            "type": "object"
          },
          "existing_style_id": {
            "example": "st_xxx",
            "type": "string"
          },
          "material": {
            "example": "bamboo",
            "type": "string"
          },
          "product_family": {
            "example": "combs",
            "type": "string"
          },
          "quantity": {
            "example": 5000,
            "type": "integer"
          }
        },
        "type": "object"
      },
      "cmd_server.RfqRequirements": {
        "properties": {
          "destination_country": {
            "example": "US",
            "type": "string"
          },
          "expected_delivery_date": {
            "example": "2026-09-30",
            "type": "string"
          },
          "incoterm": {
            "example": "FOB",
            "type": "string"
          },
          "notes": {
            "example": "Need food-grade certification",
            "type": "string"
          }
        },
        "type": "object"
      },
      "cmd_server.RfqSessionCreateRequest": {
        "properties": {
          "items": {
            "items": {
              "$ref": "#/components/schemas/cmd_server.RfqItem"
            },
            "type": "array"
          },
          "locale": {
            "example": "en",
            "type": "string"
          },
          "requirements": {
            "$ref": "#/components/schemas/cmd_server.RfqRequirements"
          }
        },
        "type": "object"
      },
      "cmd_server.RfqSessionResponse": {
        "properties": {
          "expires_at": {
            "example": "2026-07-14T12:00:00Z",
            "type": "string"
          },
          "session_id": {
            "example": "rfs_xxx",
            "type": "string"
          },
          "status": {
            "example": "draft",
            "type": "string"
          }
        },
        "type": "object"
      },
      "cmd_server.RfqSubmitRequest": {
        "properties": {
          "contact": {
            "$ref": "#/components/schemas/cmd_server.RfqContact"
          },
          "message": {
            "type": "string"
          },
          "notes": {
            "type": "string"
          },
          "session_id": {
            "example": "rfs_xxx",
            "type": "string"
          }
        },
        "required": [
          "session_id"
        ],
        "type": "object"
      },
      "cmd_server.RfqSubmitResponse": {
        "properties": {
          "quote_record_id": {
            "example": "quote_xxx",
            "type": "string"
          },
          "rfq_id": {
            "example": "rfq_xxx",
            "type": "string"
          },
          "status": {
            "example": "submitted",
            "type": "string"
          },
          "tracking_token": {
            "example": "tk_xxx",
            "type": "string"
          }
        },
        "type": "object"
      },
      "cmd_server.RfqVerificationRequest": {
        "type": "object"
      },
      "cmd_server.RfqVerifyRequest": {
        "properties": {
          "code": {
            "example": "123456",
            "type": "string"
          }
        },
        "required": [
          "code"
        ],
        "type": "object"
      },
      "cmd_server.RfqVerifyResponse": {
        "properties": {
          "expires_at": {
            "example": "2026-07-14T12:30:00Z",
            "type": "string"
          },
          "rfq_id": {
            "example": "rfq_xxx",
            "type": "string"
          },
          "rfq_token": {
            "example": "rft_xxx",
            "type": "string"
          },
          "status": {
            "example": "verified",
            "type": "string"
          }
        },
        "type": "object"
      },
      "cmd_server.SalesReply": {
        "properties": {
          "content": {
            "description": "Content 回复正文（纯文本,最长 2000 字符）。",
            "type": "string"
          },
          "replied_at": {
            "description": "RepliedAt 回复时间（RFC3339 UTC）,前端转用户本地时区显示。",
            "type": "string"
          },
          "replied_by_employee_no": {
            "description": "RepliedByEmployeeNo 回复业务员工号,用于关联 ERP 员工档案。",
            "type": "string"
          },
          "replied_by_name": {
            "description": "RepliedByName 回复业务员姓名,便于前端展示。可选,缺失时前端展示工号或\"业务员\"。",
            "type": "string"
          },
          "reply_id": {
            "description": "ReplyID ERP 生成的回复唯一 ID（格式 sr_ + ULID），用于幂等 upsert。\n独立站按此字段判断是否已存在,存在则更新 content 等字段,不存在则追加。",
            "type": "string"
          },
          "response_to": {
            "description": "ResponseTo 关联的客户留言 submitted_at（RFC3339）,用于前端串联对话线程。\n若客户删除留言或无法匹配,前端按独立时间线节点展示。",
            "type": "string"
          }
        },
        "type": "object"
      },
      "cmd_server.ThreeDInfo": {
        "properties": {
          "enabled": {
            "example": true,
            "type": "boolean"
          },
          "match_mode": {
            "example": "exact",
            "type": "string"
          }
        },
        "type": "object"
      },
      "cmd_server.aiQuoteFolderItem": {
        "properties": {
          "customization": {
            "additionalProperties": {
              "type": "string"
            },
            "type": "object"
          },
          "existing_style_id": {
            "type": "string"
          },
          "material": {
            "type": "string"
          },
          "notes": {
            "type": "string"
          },
          "product_family": {
            "type": "string"
          },
          "quantity": {
            "type": "integer"
          }
        },
        "required": [
          "quantity"
        ],
        "type": "object"
      },
      "cmd_server.aiQuoteFolderSubmitRequest": {
        "properties": {
          "contact": {
            "properties": {
              "additional_contact": {
                "type": "string"
              },
              "address": {
                "description": "任务4:身份验证弹窗可编辑 address,需保存到 QuoteRecord 快照",
                "type": "string"
              },
              "company": {
                "type": "string"
              },
              "country": {
                "type": "string"
              },
              "email": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "phone": {
                "type": "string"
              }
            },
            "required": [
              "company",
              "country",
              "email",
              "name"
            ],
            "type": "object"
          },
          "items": {
            "items": {
              "$ref": "#/components/schemas/cmd_server.aiQuoteFolderItem"
            },
            "type": "array"
          },
          "locale": {
            "type": "string"
          },
          "notes": {
            "type": "string"
          },
          "requirements": {
            "properties": {
              "destination_country": {
                "type": "string"
              },
              "expected_delivery_date": {
                "type": "string"
              },
              "incoterm": {
                "type": "string"
              },
              "notes": {
                "type": "string"
              }
            },
            "type": "object"
          }
        },
        "required": [
          "items"
        ],
        "type": "object"
      },
      "cmd_server.customerActionPublic": {
        "properties": {
          "description": {
            "type": "string"
          },
          "label": {
            "type": "string"
          },
          "required": {
            "type": "boolean"
          },
          "type": {
            "type": "string"
          },
          "type_label": {
            "description": "新增：多语言动作类型文案（如 confirm_order → 确认订单）",
            "type": "string"
          }
        },
        "type": "object"
      },
      "cmd_server.meProfile": {
        "properties": {
          "account_token": {
            "type": "string"
          },
          "account_type": {
            "type": "string"
          },
          "address": {
            "type": "string"
          },
          "address_line1": {
            "type": "string"
          },
          "address_line2": {
            "type": "string"
          },
          "city": {
            "type": "string"
          },
          "company": {
            "type": "string"
          },
          "country": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "erp_customer_id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "phone": {
            "type": "string"
          },
          "postal_code": {
            "type": "string"
          },
          "region": {
            "type": "string"
          },
          "state_province": {
            "type": "string"
          }
        },
        "type": "object"
      },
      "cmd_server.orderProgressResponse": {
        "properties": {
          "captured_at": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "image_label": {
            "type": "string"
          },
          "image_urls": {
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "source_type": {
            "type": "string"
          },
          "stage_category": {
            "type": "string"
          }
        },
        "type": "object"
      },
      "cmd_server.quoteRecordPublic": {
        "properties": {
          "account_token": {
            "type": "string"
          },
          "customer_action": {
            "$ref": "#/components/schemas/cmd_server.customerActionPublic"
          },
          "customer_responses": {
            "items": {
              "$ref": "#/components/schemas/cmd_server.CustomerResponse"
            },
            "type": "array"
          },
          "files": {
            "items": {
              "additionalProperties": {},
              "type": "object"
            },
            "type": "array"
          },
          "online_data": {
            "additionalProperties": {},
            "type": "object"
          },
          "production_tracking": {
            "$ref": "#/components/schemas/cmd_server.quoteTrackingSummary"
          },
          "public_order_no": {
            "type": "string"
          },
          "quote_id": {
            "type": "string"
          },
          "quote_no": {
            "type": "string"
          },
          "sales_contact": {
            "$ref": "#/components/schemas/cmd_server.salesContactPublic"
          },
          "sales_replies": {
            "description": "SalesReplies ERP 业务员回复历史,与 CustomerResponses 对称。\n关联对接文档：20260714-ERP-业务员回复推送对接-v1.md。",
            "items": {
              "$ref": "#/components/schemas/cmd_server.SalesReply"
            },
            "type": "array"
          },
          "shipment_tracking": {
            "$ref": "#/components/schemas/cmd_server.quoteTrackingSummary"
          },
          "status": {
            "type": "string"
          },
          "status_label": {
            "description": "新增：多语言状态文案（如 quoted → 已报价）",
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "tracking_token": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          },
          "valid_until": {
            "type": "string"
          }
        },
        "type": "object"
      },
      "cmd_server.quoteTrackingSummary": {
        "properties": {
          "stage_code": {
            "type": "string"
          },
          "stage_label": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "status_label": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          }
        },
        "type": "object"
      },
      "cmd_server.salesContactPublic": {
        "properties": {
          "email": {
            "type": "string"
          },
          "employee_no": {
            "type": "string"
          },
          "name": {
            "type": "string"
          }
        },
        "type": "object"
      },
      "cmd_server.trackingResponse": {
        "properties": {
          "estimated_ship_date": {
            "type": "string"
          },
          "exception_has_exception": {
            "type": "integer"
          },
          "last_updated_at": {
            "type": "string"
          },
          "product_family": {
            "type": "string"
          },
          "progress_events": {
            "items": {
              "$ref": "#/components/schemas/cmd_server.orderProgressResponse"
            },
            "type": "array"
          },
          "project_name": {
            "type": "string"
          },
          "public_order_no": {
            "type": "string"
          },
          "quantity_range": {
            "type": "string"
          },
          "quote_no": {
            "type": "string"
          },
          "shipment_summary": {
            "additionalProperties": {},
            "type": "object"
          },
          "tracking_token": {
            "type": "string"
          }
        },
        "type": "object"
      }
    },
    "securitySchemes": {
      "OAuth2": {
        "description": "OAuth 2.0 Authorization Code + PKCE. Scopes match API Token scopes (apt_ prefix). Access Token 15min, Refresh Token 30d idle / 180d absolute with rotation.",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "https://test.vantrecomb.com/oauth/authorize",
            "scopes": {
              "ai:rfq:read": "Read own RFQs and RFQ status (requires /ai/me/rfqs)",
              "me:files:download": "Download quote documents and upload TT proof",
              "me:orders:read": "Read own orders and production progress",
              "me:profile:read": "Read user profile and organization info",
              "me:profile:write": "Update user profile",
              "me:quotes:read": "Read own quote records",
              "me:quotes:respond": "Respond to quotes (accept, request revision, send messages)",
              "me:shipments:read": "Read own shipment tracking"
            },
            "tokenUrl": "https://test-api.vantrecomb.com/oauth/token"
          }
        },
        "type": "oauth2"
      }
    }
  },
  "info": {
    "contact": {
      "email": "api@vantrecomb.com",
      "name": "Vantre API Support"
    },
    "description": "Read the Vantre Procurement Guide first: `GET /api/v1/ai/guide`. This document publishes only AI endpoints. RFQ submission does not require email verification; status queries require the temporary 30-minute email-code authorization flow. Send an Idempotency-Key with every write request.",
    "license": {
      "name": "Proprietary"
    },
    "title": "Vantre B2B Procurement API",
    "version": "1.0"
  },
  "openapi": "3.1.0",
  "paths": {
    "/ai/catalog/products": {
      "get": {
        "description": "Aggregated product catalog query over existing-styles (real ERP nested product_data structure). Supports keyword search, multi-condition filtering (AND semantics), and pagination. Material/craft/capability/solution narratives are NOT returned here; point buyers to the copy pages listed by GET /ai/guide. Read-only aggregation, no persistence. Prices and internal costs are never included.",
        "operationId": "searchCatalogProducts",
        "parameters": [
          {
            "description": "Keyword (matches title/description/summary, multi-language)",
            "example": "bamboo",
            "in": "query",
            "name": "q",
            "type": "string"
          },
          {
            "description": "Filter by product family key (matches flat product_family or nested product_data.types)",
            "example": "combs",
            "in": "query",
            "name": "product_family",
            "type": "string"
          },
          {
            "description": "Filter by material code (matches materials/material_keys, flat or nested product_data)",
            "example": "bamboo",
            "in": "query",
            "name": "material",
            "type": "string"
          },
          {
            "description": "Filter by craft key (flat or nested; real ERP products usually carry no crafts, use copy page instead)",
            "example": "engraved",
            "in": "query",
            "name": "craft",
            "type": "string"
          },
          {
            "description": "Filter by specific existing style id",
            "example": "st_xxx",
            "in": "query",
            "name": "style_id",
            "type": "string"
          },
          {
            "description": "Filter by OEM/ODM support",
            "example": true,
            "in": "query",
            "name": "supports_oem",
            "type": "boolean"
          },
          {
            "description": "Language code (ar/de/en/es/fr/ja/pt-BR/ru/zh-CN/zh-TW)",
            "example": "en",
            "in": "query",
            "name": "locale",
            "type": "string"
          },
          {
            "default": 1,
            "description": "Page number (1-based)",
            "example": 1,
            "in": "query",
            "name": "page",
            "type": "integer"
          },
          {
            "default": 20,
            "description": "Page size (max 100)",
            "example": 20,
            "in": "query",
            "name": "page_size",
            "type": "integer"
          }
        ],
        "produces": [
          "application/json"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.CatalogProductSearchResponse"
            }
          },
          "400": {
            "description": "Invalid pagination parameters",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          }
        },
        "summary": "Search catalog products",
        "tags": [
          "ai-catalog"
        ]
      }
    },
    "/ai/catalog/products/{sku}": {
      "get": {
        "description": "Returns one product's structured AI view: name, materials, specs, images, detail page URL and whether 3D customization is enabled. Looks up by sku, then style_id, then slug. Only whitelisted structured fields are returned: no marketing HTML, no ERP internal fields, no 3D snapshot blobs.",
        "operationId": "getCatalogProduct",
        "parameters": [
          {
            "description": "Product identifier: sku, style_id or slug",
            "example": "BC-001",
            "in": "path",
            "name": "sku",
            "required": true,
            "type": "string"
          },
          {
            "default": "en",
            "description": "Language code (ar/de/en/es/fr/ja/pt-BR/ru/zh-CN/zh-TW)",
            "example": "en",
            "in": "query",
            "name": "locale",
            "type": "string"
          }
        ],
        "produces": [
          "application/json"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.CatalogProductDetailResponse"
            }
          },
          "404": {
            "description": "Product not found for the requested locale",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          }
        },
        "summary": "Get catalog product detail",
        "tags": [
          "ai-catalog"
        ]
      }
    },
    "/ai/guide": {
      "get": {
        "description": "Returns the concise Vantre procurement guide, including the temporary RFQ email-code authorization flow used before an RFQ status query.",
        "operationId": "getAiGuide",
        "produces": [
          "text/plain"
        ],
        "responses": {
          "200": {
            "description": "Markdown procurement guide",
            "schema": {
              "type": "string"
            }
          },
          "500": {
            "description": "Guide unavailable",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          }
        },
        "summary": "Get Vantre procurement guide",
        "tags": [
          "ai-guide"
        ]
      }
    },
    "/ai/me/files": {
      "get": {
        "description": "Returns ERP- or site-configured files from the authenticated user's quote records. This API is download-only and never accepts customer uploads. Files are normally also sent by email; use this API when an email attachment is unavailable.",
        "operationId": "listMyDocuments",
        "parameters": [
          {
            "description": "Bearer apt_xxx (API Token)",
            "in": "header",
            "name": "Authorization",
            "type": "string"
          },
          {
            "description": "Browser session token",
            "in": "header",
            "name": "X-Account-Token",
            "type": "string"
          },
          {
            "default": 1,
            "description": "Page number (1-based)",
            "example": 1,
            "in": "query",
            "name": "page",
            "type": "integer"
          },
          {
            "default": 20,
            "description": "Page size (1-50)",
            "example": 20,
            "in": "query",
            "name": "page_size",
            "type": "integer"
          }
        ],
        "produces": [
          "application/json"
        ],
        "responses": {
          "200": {
            "description": "File list with pagination meta",
            "schema": {
              "additionalProperties": true,
              "type": "object"
            }
          },
          "401": {
            "description": "Authentication required",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          }
        },
        "security": [
          {
            "OAuth2": [
              "me:files:download"
            ]
          }
        ],
        "summary": "List current user's files",
        "tags": [
          "me"
        ]
      }
    },
    "/ai/me/files/{document_id}/download-link": {
      "post": {
        "consumes": [
          "application/json"
        ],
        "description": "Issues a short-lived download URL for an ERP- or site-configured file. This is a read-only delivery path; customer uploads must be sent by email to the assigned salesperson.",
        "operationId": "createDocumentDownloadLink",
        "parameters": [
          {
            "description": "Bearer apt_xxx (API Token)",
            "in": "header",
            "name": "Authorization",
            "type": "string"
          },
          {
            "description": "Browser session token",
            "in": "header",
            "name": "X-Account-Token",
            "type": "string"
          },
          {
            "description": "Document ID (format: quote_id:file_id)",
            "example": "quote_xxx:file-001",
            "in": "path",
            "name": "document_id",
            "required": true,
            "type": "string"
          },
          {
            "description": "Idempotency key for duplicate protection",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "type": "string"
          }
        ],
        "produces": [
          "application/json"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "additionalProperties": true,
              "type": "object"
            }
          },
          "401": {
            "description": "Authentication required",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          },
          "404": {
            "description": "Document or quote not found",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          },
          "409": {
            "description": "File has no source URL",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          }
        },
        "security": [
          {
            "OAuth2": [
              "me:files:download"
            ]
          }
        ],
        "summary": "Create file download link",
        "tags": [
          "me"
        ]
      }
    },
    "/ai/me/orders": {
      "get": {
        "description": "Returns paginated order summaries for quotes that have a tracking_token. Each summary includes order_id (tracking_token), public_order_no, status, and estimated_ship_date.",
        "operationId": "listMyOrders",
        "parameters": [
          {
            "description": "Bearer apt_xxx (API Token)",
            "in": "header",
            "name": "Authorization",
            "type": "string"
          },
          {
            "description": "Browser session token",
            "in": "header",
            "name": "X-Account-Token",
            "type": "string"
          },
          {
            "default": 1,
            "description": "Page number (1-based)",
            "example": 1,
            "in": "query",
            "name": "page",
            "type": "integer"
          },
          {
            "default": 10,
            "description": "Page size (1-50)",
            "example": 10,
            "in": "query",
            "name": "page_size",
            "type": "integer"
          }
        ],
        "produces": [
          "application/json"
        ],
        "responses": {
          "200": {
            "description": "Order list with pagination meta",
            "schema": {
              "additionalProperties": true,
              "type": "object"
            }
          },
          "401": {
            "description": "Authentication required",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          }
        },
        "security": [
          {
            "OAuth2": [
              "me:orders:read"
            ]
          }
        ],
        "summary": "List current user's orders",
        "tags": [
          "me"
        ]
      }
    },
    "/ai/me/orders/{order_id}": {
      "get": {
        "description": "Returns production tracking details for an order by tracking_token, including progress events. Object-level authorization: order must belong to the authenticated user (verified via quote record ownership).",
        "operationId": "getOrderStatus",
        "parameters": [
          {
            "description": "Bearer apt_xxx (API Token)",
            "in": "header",
            "name": "Authorization",
            "type": "string"
          },
          {
            "description": "Browser session token",
            "in": "header",
            "name": "X-Account-Token",
            "type": "string"
          },
          {
            "description": "Order ID (tracking_token)",
            "example": "tk_xxx",
            "in": "path",
            "name": "order_id",
            "required": true,
            "type": "string"
          }
        ],
        "produces": [
          "application/json"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.trackingResponse"
            }
          },
          "401": {
            "description": "Authentication required",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          },
          "404": {
            "description": "Order not found or not accessible",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          }
        },
        "security": [
          {
            "OAuth2": [
              "me:orders:read"
            ]
          }
        ],
        "summary": "Get order status",
        "tags": [
          "me"
        ]
      }
    },
    "/ai/me/organizations": {
      "get": {
        "description": "Returns organizations the authenticated user belongs to. Currently returns simple account info (account_type, company, erp_customer_id). Extensible for multi-organization support in the future.",
        "operationId": "getMyOrganizations",
        "parameters": [
          {
            "description": "Bearer apt_xxx (API Token)",
            "in": "header",
            "name": "Authorization",
            "type": "string"
          },
          {
            "description": "Browser session token",
            "in": "header",
            "name": "X-Account-Token",
            "type": "string"
          }
        ],
        "produces": [
          "application/json"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "additionalProperties": true,
              "type": "object"
            }
          },
          "401": {
            "description": "Authentication required",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          },
          "404": {
            "description": "Account not found",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          }
        },
        "security": [
          {
            "OAuth2": [
              "me:profile:read"
            ]
          }
        ],
        "summary": "Get current user's organizations",
        "tags": [
          "me"
        ]
      }
    },
    "/ai/me/profile": {
      "get": {
        "description": "Returns the authenticated user's profile information (email, name, company, phone, country, etc.). Sensitive fields like password_hash are excluded. Supports both API Token and browser session authentication.",
        "operationId": "getMyProfile",
        "parameters": [
          {
            "description": "Bearer apt_xxx (API Token)",
            "in": "header",
            "name": "Authorization",
            "type": "string"
          },
          {
            "description": "Browser session token",
            "in": "header",
            "name": "X-Account-Token",
            "type": "string"
          }
        ],
        "produces": [
          "application/json"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.meProfile"
            }
          },
          "401": {
            "description": "Authentication required",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          },
          "404": {
            "description": "Account not found",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          }
        },
        "security": [
          {
            "OAuth2": [
              "me:profile:read"
            ]
          }
        ],
        "summary": "Get current user profile",
        "tags": [
          "me"
        ]
      },
      "patch": {
        "consumes": [
          "application/json"
        ],
        "description": "Updates default contact or shipping-address fields for future purchasing. For an existing order, send a quote-record message so sales can confirm the order-specific change.",
        "operationId": "updateMyProfile",
        "parameters": [
          {
            "description": "Bearer apt_xxx (API Token)",
            "in": "header",
            "name": "Authorization",
            "type": "string"
          },
          {
            "description": "Browser session token",
            "in": "header",
            "name": "X-Account-Token",
            "type": "string"
          },
          {
            "description": "Idempotency key for duplicate protection",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "type": "string"
          },
          {
            "description": "Profile fields to update",
            "in": "body",
            "name": "body",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/cmd_server.AccountProfileUpdateRequest"
            }
          }
        ],
        "produces": [
          "application/json"
        ],
        "responses": {
          "200": {
            "description": "Updated account profile",
            "schema": {
              "additionalProperties": true,
              "type": "object"
            }
          },
          "400": {
            "description": "Invalid request",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          },
          "401": {
            "description": "Authentication required",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          },
          "404": {
            "description": "Account not found",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          }
        },
        "security": [
          {
            "OAuth2": [
              "me:profile:write"
            ]
          }
        ],
        "summary": "Update current user's default profile",
        "tags": [
          "me"
        ]
      }
    },
    "/ai/me/quotes": {
      "get": {
        "description": "Returns paginated quote records for the authenticated user. Filters by business status. Internal fields (sync_status, pulled_at, acked_at) are excluded from the response.",
        "operationId": "listMyQuotes",
        "parameters": [
          {
            "description": "Bearer apt_xxx (API Token)",
            "in": "header",
            "name": "Authorization",
            "type": "string"
          },
          {
            "description": "Browser session token",
            "in": "header",
            "name": "X-Account-Token",
            "type": "string"
          },
          {
            "description": "Filter by business status (e.g. quoted, order_created)",
            "example": "quoted",
            "in": "query",
            "name": "status",
            "type": "string"
          },
          {
            "default": 1,
            "description": "Page number (1-based)",
            "example": 1,
            "in": "query",
            "name": "page",
            "type": "integer"
          },
          {
            "default": 10,
            "description": "Page size (1-50)",
            "example": 10,
            "in": "query",
            "name": "page_size",
            "type": "integer"
          }
        ],
        "produces": [
          "application/json"
        ],
        "responses": {
          "200": {
            "description": "Quote list with pagination meta",
            "schema": {
              "additionalProperties": true,
              "type": "object"
            }
          },
          "401": {
            "description": "Authentication required",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          }
        },
        "security": [
          {
            "OAuth2": [
              "me:quotes:read"
            ]
          }
        ],
        "summary": "List current user's quotes",
        "tags": [
          "me"
        ]
      }
    },
    "/ai/me/quotes/{quote_id}": {
      "get": {
        "description": "Returns full details of a specific quote record, including customer_action and customer_responses. Object-level authorization: quote must belong to the authenticated user.",
        "operationId": "getMyQuote",
        "parameters": [
          {
            "description": "Bearer apt_xxx (API Token)",
            "in": "header",
            "name": "Authorization",
            "type": "string"
          },
          {
            "description": "Browser session token",
            "in": "header",
            "name": "X-Account-Token",
            "type": "string"
          },
          {
            "description": "Quote ID",
            "example": "quote_xxx",
            "in": "path",
            "name": "quote_id",
            "required": true,
            "type": "string"
          }
        ],
        "produces": [
          "application/json"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.quoteRecordPublic"
            }
          },
          "401": {
            "description": "Authentication required",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          },
          "404": {
            "description": "Quote not found or not owned by caller",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          }
        },
        "security": [
          {
            "OAuth2": [
              "me:quotes:read"
            ]
          }
        ],
        "summary": "Get a specific quote",
        "tags": [
          "me"
        ]
      }
    },
    "/ai/me/quotes/{quote_id}/accept": {
      "post": {
        "consumes": [
          "application/json"
        ],
        "description": "Accepts a quote by wrapping respondQuoteRecord with action=approve. Contact info (name, email, phone, address) is required. This is a write operation that requires explicit customer confirmation — AI must NOT auto-execute this. Idempotency-Key recommended.",
        "operationId": "acceptQuote",
        "parameters": [
          {
            "description": "Bearer apt_xxx (API Token)",
            "in": "header",
            "name": "Authorization",
            "type": "string"
          },
          {
            "description": "Browser session token",
            "in": "header",
            "name": "X-Account-Token",
            "type": "string"
          },
          {
            "description": "Quote ID",
            "example": "quote_xxx",
            "in": "path",
            "name": "quote_id",
            "required": true,
            "type": "string"
          },
          {
            "description": "Idempotency key for duplicate protection",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "type": "string"
          },
          {
            "description": "Acceptance payload",
            "in": "body",
            "name": "body",
            "required": true,
            "schema": {
              "type": "object"
            }
          }
        ],
        "produces": [
          "application/json"
        ],
        "responses": {
          "202": {
            "description": "Accepted",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.quoteRecordPublic"
            }
          },
          "400": {
            "description": "Missing required contact fields",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          },
          "401": {
            "description": "Authentication required",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          },
          "404": {
            "description": "Quote not found",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          }
        },
        "security": [
          {
            "OAuth2": [
              "me:quotes:respond"
            ]
          }
        ],
        "summary": "Accept a quote",
        "tags": [
          "me"
        ]
      }
    },
    "/ai/me/quotes/{quote_id}/messages": {
      "post": {
        "consumes": [
          "application/json"
        ],
        "description": "Sends a free-text message to the sales team by wrapping respondQuoteRecord with action=message. Messages do NOT trigger status changes and do NOT clear pending customer_action. Returns 202 Accepted.",
        "operationId": "sendMessage",
        "parameters": [
          {
            "description": "Bearer apt_xxx (API Token)",
            "in": "header",
            "name": "Authorization",
            "type": "string"
          },
          {
            "description": "Browser session token",
            "in": "header",
            "name": "X-Account-Token",
            "type": "string"
          },
          {
            "description": "Quote ID",
            "example": "quote_xxx",
            "in": "path",
            "name": "quote_id",
            "required": true,
            "type": "string"
          },
          {
            "description": "Idempotency key for duplicate protection",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "type": "string"
          },
          {
            "description": "Message payload",
            "in": "body",
            "name": "body",
            "required": true,
            "schema": {
              "type": "object"
            }
          }
        ],
        "produces": [
          "application/json"
        ],
        "responses": {
          "202": {
            "description": "Accepted",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.quoteRecordPublic"
            }
          },
          "400": {
            "description": "Invalid request body or missing note",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          },
          "401": {
            "description": "Authentication required",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          },
          "404": {
            "description": "Quote not found",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          }
        },
        "security": [
          {
            "OAuth2": [
              "me:quotes:respond"
            ]
          }
        ],
        "summary": "Send a message on a quote",
        "tags": [
          "me"
        ]
      }
    },
    "/ai/me/quotes/{quote_id}/request-revision": {
      "post": {
        "consumes": [
          "application/json"
        ],
        "description": "Requests a revision to a quote by wrapping respondQuoteRecord with action=reject. Note must be at least 20 characters. This is a write operation that requires explicit customer confirmation — AI must NOT auto-execute this. Idempotency-Key recommended.",
        "operationId": "requestQuoteRevision",
        "parameters": [
          {
            "description": "Bearer apt_xxx (API Token)",
            "in": "header",
            "name": "Authorization",
            "type": "string"
          },
          {
            "description": "Browser session token",
            "in": "header",
            "name": "X-Account-Token",
            "type": "string"
          },
          {
            "description": "Quote ID",
            "example": "quote_xxx",
            "in": "path",
            "name": "quote_id",
            "required": true,
            "type": "string"
          },
          {
            "description": "Idempotency key for duplicate protection",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "type": "string"
          },
          {
            "description": "Revision request payload",
            "in": "body",
            "name": "body",
            "required": true,
            "schema": {
              "type": "object"
            }
          }
        ],
        "produces": [
          "application/json"
        ],
        "responses": {
          "202": {
            "description": "Accepted",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.quoteRecordPublic"
            }
          },
          "400": {
            "description": "Note too short (\u003c 20 characters)",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          },
          "401": {
            "description": "Authentication required",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          },
          "404": {
            "description": "Quote not found",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          }
        },
        "security": [
          {
            "OAuth2": [
              "me:quotes:respond"
            ]
          }
        ],
        "summary": "Request quote revision",
        "tags": [
          "me"
        ]
      }
    },
    "/ai/me/rfqs": {
      "get": {
        "description": "Returns paginated RFQ summaries for the authenticated user. RFQs are matched via Metadata.account_token field in the inquiry envelope.",
        "operationId": "listMyRfqs",
        "parameters": [
          {
            "description": "Bearer apt_xxx (API Token)",
            "in": "header",
            "name": "Authorization",
            "type": "string"
          },
          {
            "description": "Browser session token",
            "in": "header",
            "name": "X-Account-Token",
            "type": "string"
          },
          {
            "default": 1,
            "description": "Page number (1-based)",
            "example": 1,
            "in": "query",
            "name": "page",
            "type": "integer"
          },
          {
            "default": 20,
            "description": "Page size (1-50)",
            "example": 20,
            "in": "query",
            "name": "page_size",
            "type": "integer"
          }
        ],
        "produces": [
          "application/json"
        ],
        "responses": {
          "200": {
            "description": "RFQ list with pagination meta",
            "schema": {
              "additionalProperties": true,
              "type": "object"
            }
          },
          "401": {
            "description": "Authentication required",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          }
        },
        "security": [
          {
            "OAuth2": [
              "ai:rfq:read"
            ]
          }
        ],
        "summary": "List current user's RFQs",
        "tags": [
          "me"
        ]
      }
    },
    "/ai/me/rfqs/{rfq_id}": {
      "get": {
        "description": "Returns details of a specific RFQ. Object-level authorization: RFQ must belong to the authenticated user (verified via Metadata.account_token).",
        "operationId": "getMyRfq",
        "parameters": [
          {
            "description": "Bearer apt_xxx (API Token)",
            "in": "header",
            "name": "Authorization",
            "type": "string"
          },
          {
            "description": "Browser session token",
            "in": "header",
            "name": "X-Account-Token",
            "type": "string"
          },
          {
            "description": "RFQ ID",
            "example": "inq_xxx",
            "in": "path",
            "name": "rfq_id",
            "required": true,
            "type": "string"
          }
        ],
        "produces": [
          "application/json"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "additionalProperties": true,
              "type": "object"
            }
          },
          "401": {
            "description": "Authentication required",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          },
          "404": {
            "description": "RFQ not found or not accessible",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          }
        },
        "security": [
          {
            "OAuth2": [
              "ai:rfq:read"
            ]
          }
        ],
        "summary": "Get a specific RFQ",
        "tags": [
          "me"
        ]
      }
    },
    "/ai/me/shipments": {
      "get": {
        "description": "Returns paginated shipment summaries for quotes that have a tracking_token. Each summary includes shipment_id (tracking_token), public_order_no, status, and last_updated_at.",
        "operationId": "listMyShipments",
        "parameters": [
          {
            "description": "Bearer apt_xxx (API Token)",
            "in": "header",
            "name": "Authorization",
            "type": "string"
          },
          {
            "description": "Browser session token",
            "in": "header",
            "name": "X-Account-Token",
            "type": "string"
          },
          {
            "default": 1,
            "description": "Page number (1-based)",
            "example": 1,
            "in": "query",
            "name": "page",
            "type": "integer"
          },
          {
            "default": 10,
            "description": "Page size (1-50)",
            "example": 10,
            "in": "query",
            "name": "page_size",
            "type": "integer"
          }
        ],
        "produces": [
          "application/json"
        ],
        "responses": {
          "200": {
            "description": "Shipment list with pagination meta",
            "schema": {
              "additionalProperties": true,
              "type": "object"
            }
          },
          "401": {
            "description": "Authentication required",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          }
        },
        "security": [
          {
            "OAuth2": [
              "me:shipments:read"
            ]
          }
        ],
        "summary": "List current user's shipments",
        "tags": [
          "me"
        ]
      }
    },
    "/ai/me/shipments/{shipment_id}": {
      "get": {
        "description": "Returns shipment tracking events for an order by tracking_token. Object-level authorization: shipment must belong to the authenticated user.",
        "operationId": "getMeShipment",
        "parameters": [
          {
            "description": "Bearer apt_xxx (API Token)",
            "in": "header",
            "name": "Authorization",
            "type": "string"
          },
          {
            "description": "Browser session token",
            "in": "header",
            "name": "X-Account-Token",
            "type": "string"
          },
          {
            "description": "Shipment ID (tracking_token)",
            "example": "tk_xxx",
            "in": "path",
            "name": "shipment_id",
            "required": true,
            "type": "string"
          }
        ],
        "produces": [
          "application/json"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "additionalProperties": true,
              "type": "object"
            }
          },
          "401": {
            "description": "Authentication required",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          },
          "404": {
            "description": "Shipment not found or not accessible",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          }
        },
        "security": [
          {
            "OAuth2": [
              "me:shipments:read"
            ]
          }
        ],
        "summary": "Get shipment details",
        "tags": [
          "me"
        ]
      }
    },
    "/ai/quote-folder/submit": {
      "post": {
        "consumes": [
          "application/json"
        ],
        "description": "Submits multiple products as a single RFQ in one request. Ideal when the user has multiple product selections. No session creation needed — pass items array directly with contact info. Anonymous (no X-Account-Token). Reuses the same persistence and query flow as /ai/rfqs. Idempotency-Key required by middleware.",
        "operationId": "submitAiQuoteFolder",
        "parameters": [
          {
            "description": "Idempotency key to prevent duplicate submission (required by middleware)",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "type": "string"
          },
          {
            "description": "Language code (ar/de/en/es/fr/ja/pt-BR/ru/zh-CN/zh-TW)",
            "example": "en",
            "in": "query",
            "name": "locale",
            "type": "string"
          },
          {
            "description": "Batch submission with items array and contact info",
            "in": "body",
            "name": "body",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/cmd_server.aiQuoteFolderSubmitRequest"
            }
          }
        ],
        "produces": [
          "application/json"
        ],
        "responses": {
          "201": {
            "description": "Created",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.RfqSubmitResponse"
            }
          },
          "400": {
            "description": "Empty items or missing required contact fields",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          },
          "500": {
            "description": "Encryption or persistence failure",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          }
        },
        "summary": "Submit AI quote folder (batch)",
        "tags": [
          "ai-rfq"
        ]
      }
    },
    "/ai/rfq-sessions": {
      "post": {
        "consumes": [
          "application/json"
        ],
        "description": "Creates an anonymous AI RFQ draft session with items and requirements. The session is valid for 24 hours and lives in memory only (not persisted). Anonymous callers can use this endpoint to bootstrap a quote request. Returns session_id, status=draft, and expires_at.",
        "operationId": "createRfqSession",
        "parameters": [
          {
            "description": "Idempotency key to prevent duplicate draft creation (required by middleware)",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "type": "string"
          },
          {
            "description": "Language code (ar/de/en/es/fr/ja/pt-BR/ru/zh-CN/zh-TW)",
            "example": "en",
            "in": "query",
            "name": "locale",
            "type": "string"
          },
          {
            "description": "RFQ draft payload (locale, items, requirements)",
            "in": "body",
            "name": "body",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/cmd_server.RfqSessionCreateRequest"
            }
          }
        ],
        "produces": [
          "application/json"
        ],
        "responses": {
          "201": {
            "description": "Created",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.RfqSessionResponse"
            }
          },
          "400": {
            "description": "Empty items or invalid payload",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          }
        },
        "summary": "Create AI RFQ draft session",
        "tags": [
          "ai-rfq"
        ]
      }
    },
    "/ai/rfqs": {
      "post": {
        "consumes": [
          "application/json"
        ],
        "description": "Submits the AI RFQ draft session as a formal quote request. No email verification required (new flow). Requires full contact info: name, company, email, country (all required). Auto-creates or associates a registered account by email. Reuses the existing encryptInquiryPayload + InquiryEnvelope + QuoteRecord persistence chain (FormType=ai_rfq_submission, LeadSource=ai_rfq). Idempotency-Key required by middleware. Returns rfq_id, quote_record_id, tracking_token, status=submitted.",
        "operationId": "submitRfq",
        "parameters": [
          {
            "description": "Idempotency key to prevent duplicate RFQ submission (required by middleware)",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "type": "string"
          },
          {
            "description": "Language code (ar/de/en/es/fr/ja/pt-BR/ru/zh-CN/zh-TW)",
            "example": "en",
            "in": "query",
            "name": "locale",
            "type": "string"
          },
          {
            "description": "Submission payload (session_id, contact with name/company/email/country, notes)",
            "in": "body",
            "name": "body",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/cmd_server.RfqSubmitRequest"
            }
          }
        ],
        "produces": [
          "application/json"
        ],
        "responses": {
          "201": {
            "description": "Created",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.RfqSubmitResponse"
            }
          },
          "400": {
            "description": "Invalid payload or missing required contact fields",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          },
          "404": {
            "description": "Session not found",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          },
          "410": {
            "description": "Session expired",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          },
          "500": {
            "description": "Encryption or persistence failure",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          }
        },
        "summary": "Submit AI RFQ",
        "tags": [
          "ai-rfq"
        ]
      }
    },
    "/ai/rfqs/{rfq_id}": {
      "get": {
        "description": "Returns the submitted AI RFQ by rfq_id. Requires X-RFQ-Token header matching the query token issued by verifyRfqSession (cross-RFQ queries are forbidden). The token is valid for 30 minutes. Returns rfq_id, status (submitted_to_erp), quote_record summary, and submitted_at.",
        "operationId": "getRfq",
        "parameters": [
          {
            "description": "Query token issued by verifyRfqSession (30 minutes valid)",
            "in": "header",
            "name": "X-RFQ-Token",
            "required": true,
            "type": "string"
          },
          {
            "description": "RFQ ID returned by submitRfq",
            "example": "rfq_xxx",
            "in": "path",
            "name": "rfq_id",
            "required": true,
            "type": "string"
          },
          {
            "description": "Language code (ar/de/en/es/fr/ja/pt-BR/ru/zh-CN/zh-TW)",
            "example": "en",
            "in": "query",
            "name": "locale",
            "type": "string"
          }
        ],
        "produces": [
          "application/json"
        ],
        "responses": {
          "200": {
            "description": "RFQ details with quote_record summary",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.RfqGetResponse"
            }
          },
          "401": {
            "description": "Missing or expired X-RFQ-Token",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          },
          "403": {
            "description": "Token does not match this RFQ",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          },
          "404": {
            "description": "RFQ not found",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          }
        },
        "summary": "Get AI RFQ",
        "tags": [
          "ai-rfq"
        ]
      }
    },
    "/ai/rfqs/{rfq_id}/resend-verification": {
      "post": {
        "consumes": [
          "application/json"
        ],
        "description": "Resends the email verification code for an AI RFQ. Same behavior as sendRfqVerification; provided as a separate endpoint for clients that prefer explicit resend semantics. Looks up the QuoteRecord by rfq_id to get the email.",
        "operationId": "resendRfqVerification",
        "parameters": [
          {
            "description": "Idempotency key to prevent duplicate resend (required by middleware)",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "type": "string"
          },
          {
            "description": "RFQ ID returned by submitRfq",
            "example": "rfq_xxx",
            "in": "path",
            "name": "rfq_id",
            "required": true,
            "type": "string"
          },
          {
            "description": "Language code (ar/de/en/es/fr/ja/pt-BR/ru/zh-CN/zh-TW)",
            "example": "en",
            "in": "query",
            "name": "locale",
            "type": "string"
          },
          {
            "description": "Empty body (email is obtained from the QuoteRecord)",
            "in": "body",
            "name": "body",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.RfqVerificationRequest"
            }
          }
        ],
        "produces": [
          "application/json"
        ],
        "responses": {
          "200": {
            "description": "verification_sent status with expires_at",
            "schema": {
              "additionalProperties": true,
              "type": "object"
            }
          },
          "404": {
            "description": "RFQ not found",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          },
          "429": {
            "description": "Too many verification requests",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          },
          "500": {
            "description": "Failed to issue code or send email",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          }
        },
        "summary": "Resend AI RFQ email verification code",
        "tags": [
          "ai-rfq"
        ]
      }
    },
    "/ai/rfqs/{rfq_id}/send-verification": {
      "post": {
        "consumes": [
          "application/json"
        ],
        "description": "Issues and sends an email verification code for querying an AI RFQ. New flow: looks up the QuoteRecord by rfq_id to get the email (no session required, as the session may have expired). Reuses issueEmailCodeLocked with purpose=inquiry_email, TTL=30 minutes. In dev mode (DEV_RETURN_EMAIL_CODE=true) the code is returned in the response for testing.",
        "operationId": "sendRfqVerification",
        "parameters": [
          {
            "description": "Idempotency key to prevent duplicate verification emails (required by middleware)",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "type": "string"
          },
          {
            "description": "RFQ ID returned by submitRfq",
            "example": "rfq_xxx",
            "in": "path",
            "name": "rfq_id",
            "required": true,
            "type": "string"
          },
          {
            "description": "Language code (ar/de/en/es/fr/ja/pt-BR/ru/zh-CN/zh-TW)",
            "example": "en",
            "in": "query",
            "name": "locale",
            "type": "string"
          },
          {
            "description": "Empty body (email is obtained from the QuoteRecord)",
            "in": "body",
            "name": "body",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.RfqVerificationRequest"
            }
          }
        ],
        "produces": [
          "application/json"
        ],
        "responses": {
          "200": {
            "description": "verification_sent status with expires_at",
            "schema": {
              "additionalProperties": true,
              "type": "object"
            }
          },
          "404": {
            "description": "RFQ not found",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          },
          "429": {
            "description": "Too many verification requests",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          },
          "500": {
            "description": "Failed to issue code or send email",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          }
        },
        "summary": "Send AI RFQ email verification code",
        "tags": [
          "ai-rfq"
        ]
      }
    },
    "/ai/rfqs/{rfq_id}/verify": {
      "post": {
        "consumes": [
          "application/json"
        ],
        "description": "Verifies the email code issued by sendRfqVerification and issues a query Token (rft_xxx, 30 minutes valid, bound to rfq_id). Looks up the QuoteRecord by rfq_id to get the email and persists the token to QuoteRecord.OnlineData. Works for both RFQ session submissions and quote-folder batch submissions (no session required). Returns 404 if RFQ not found, 400 if the code is wrong.",
        "operationId": "verifyRfqSession",
        "parameters": [
          {
            "description": "Idempotency key to prevent duplicate verification (required by middleware)",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "type": "string"
          },
          {
            "description": "RFQ ID returned by submitRfq",
            "example": "rfq_xxx",
            "in": "path",
            "name": "rfq_id",
            "required": true,
            "type": "string"
          },
          {
            "description": "Language code (ar/de/en/es/fr/ja/pt-BR/ru/zh-CN/zh-TW)",
            "example": "en",
            "in": "query",
            "name": "locale",
            "type": "string"
          },
          {
            "description": "Verification code (email is obtained from the QuoteRecord)",
            "in": "body",
            "name": "body",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/cmd_server.RfqVerifyRequest"
            }
          }
        ],
        "produces": [
          "application/json"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.RfqVerifyResponse"
            }
          },
          "400": {
            "description": "Wrong code or missing fields",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          },
          "404": {
            "description": "RFQ not found",
            "schema": {
              "$ref": "#/components/schemas/cmd_server.ProblemDetail"
            }
          }
        },
        "summary": "Verify AI RFQ email code",
        "tags": [
          "ai-rfq"
        ]
      }
    }
  },
  "servers": [
    {
      "url": "https://test-api.vantrecomb.com/api/v1"
    }
  ],
  "tags": [
    {
      "description": "AI-optimized catalog endpoints with fixed schema, filtered fields, and pagination. Replaces /api/v1/public/* for AI usage.",
      "name": "ai-catalog"
    },
    {
      "description": "AI RFQ submission and temporary email-code authorization endpoints.",
      "name": "ai-rfq"
    },
    {
      "description": "Authenticated user endpoints (requires API Token apt_ or browser session). Covers profile, quotes, orders, shipments, documents, RFQs. Scopes enforced via requireScopes middleware.",
      "name": "me"
    },
    {
      "description": "Concise procurement workflow for AI assistants.",
      "name": "ai-guide"
    }
  ]
}