{
  "openapi": "3.1.0",
  "info": {
    "title": "AIMarket · 门店检索与预约接口（AI 助手可用）",
    "version": "0.1.0",
    "description": "平台级接口。AI 助手可以检索门店、读取门店结构化数据、占位预约。确认预约必须由本人确认。 使用分层见 x-usage-policy：公开数据永久免费；API/MCP 目前免费，未来设免费配额，超限需商业授权；禁止整体转售；门店可随时下线。",
    "contact": {
      "name": "AIMarket",
      "url": "https://aimarket.show"
    }
  },
  "x-usage-policy": {
    "publicData": {
      "endpoints": [
        "/directory.txt",
        "/merchants.json",
        "/shops/<slug>/facts.json",
        "/shops/<slug>/card.txt",
        "/s/<城市>/<范围>/pick.json"
      ],
      "terms": "永久免费、无鉴权。欢迎搜索引擎与 AI 助手读取、索引、引用；请在展示时注明来源。"
    },
    "apiAndMcp": {
      "endpoints": [
        "/api/*",
        "/mcp"
      ],
      "terms": "目前免费。未来将设置每日免费配额；超出配额或用于商业场景需申请商业授权。",
      "note": "现有调用不受影响；规则调整会提前公示。"
    },
    "prohibited": [
      "整体转售数据集",
      "伪造或篡改数据后冒充平台发布",
      "用于欺诈、骚扰、非法营销",
      "移除来源与更新时间标记"
    ],
    "merchantRights": "门店可随时要求下线，平台同步删除网页数据与仓库副本。",
    "qualityDisclaimer": "数据由门店维护、平台核验，不构成对服务质量的保证；引用价格时请附带数据中的价格核实时间。"
  },
  "servers": [
    {
      "url": "https://aimarket.show"
    }
  ],
  "paths": {
    "/merchants.json": {
      "get": {
        "operationId": "listAllMerchants",
        "summary": "全部商户机器可读数据（推荐 AI 首选）",
        "responses": {
          "200": {
            "description": "JSON"
          }
        }
      }
    },
    "/api/search": {
      "get": {
        "operationId": "searchMerchants",
        "summary": "按关键词或品类检索门店",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "关键词，例：拼豆"
          },
          {
            "name": "category",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "品类，例：亲子"
          },
          {
            "name": "city",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 20
            }
          }
        ],
        "responses": {
          "200": {
            "description": "匹配的门店列表"
          }
        }
      }
    },
    "/api/shop": {
      "get": {
        "operationId": "getShop",
        "summary": "按 slug 取单店完整数据",
        "parameters": [
          {
            "name": "slug",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "单店数据"
          },
          "404": {
            "description": "没有这家店"
          }
        }
      }
    },
    "/mcp-tools.json": {
      "get": {
        "operationId": "getToolContract",
        "summary": "AI 工具契约：读门店 + 写门店（入驻/运营）",
        "responses": {
          "200": {
            "description": "工具定义 JSON"
          }
        }
      }
    },
    "/api/concierge": {
      "post": {
        "summary": "一句话入口：找店/问房态/问价格/下单",
        "description": "自动识别意图，返回 answer + shops + actions；下单需 confirm=true，缺参数会要求补充。",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "q"
                ],
                "properties": {
                  "q": {
                    "type": "string"
                  },
                  "slug": {
                    "type": "string"
                  },
                  "date": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  },
                  "phone": {
                    "type": "string"
                  },
                  "room": {
                    "type": "string"
                  },
                  "guests": {
                    "type": "string"
                  },
                  "confirm": {
                    "type": "boolean"
                  },
                  "channel": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "回答 + 门店 + 动作"
          }
        }
      }
    },
    "/api/booking": {
      "post": {
        "summary": "提交预订/订座（AI 可调用，需用户明确同意）",
        "description": "酒店用 kind=stay（传 checkin/checkout/room）；餐厅用 kind=table（传 date/slot/party）。返回 6 位预订码。同手机号+同条件 15 分钟内重复调用会返回原码（幂等）。AI 必须传 src=ai，且必须先向用户复述日期/时间/人数并得到同意。",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "slug": {
                    "type": "string"
                  },
                  "kind": {
                    "type": "string",
                    "enum": [
                      "stay",
                      "table"
                    ]
                  },
                  "date": {
                    "type": "string"
                  },
                  "slot": {
                    "type": "string"
                  },
                  "checkin": {
                    "type": "string"
                  },
                  "checkout": {
                    "type": "string"
                  },
                  "room": {
                    "type": "string"
                  },
                  "party": {
                    "type": "integer"
                  },
                  "name": {
                    "type": "string"
                  },
                  "phone": {
                    "type": "string"
                  },
                  "note": {
                    "type": "string"
                  },
                  "src": {
                    "type": "string",
                    "description": "渠道：ai / web / qr"
                  }
                },
                "required": [
                  "slug",
                  "name",
                  "phone"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "预订已创建，返回 code"
          },
          "429": {
            "description": "同一手机号 1 小时内预订过多"
          }
        }
      },
      "get": {
        "summary": "查询预订状态（code + phone）",
        "parameters": [
          {
            "name": "code",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "phone",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "返回 booking.status：pending/confirmed/checked_in/rejected/no_show"
          }
        }
      }
    },
    "/api/booking/status": {
      "post": {
        "summary": "商家操作预订状态（需商家 token）",
        "description": "action: confirm / reject / checkin / noshow",
        "responses": {
          "200": {
            "description": "状态已更新"
          }
        }
      }
    },
    "/api/apply": {
      "post": {
        "operationId": "applyMerchant",
        "summary": "商户入驻申请（任何 AI 都能替门店提交）",
        "description": "提交门店名称、品类、城市、地址、简介，返回 slug 与 claimCode（该门店的唯一写入凭证）。开放申请，无需商务对接。",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name",
                  "category",
                  "city",
                  "address",
                  "intro"
                ],
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "category": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "city": {
                    "type": "string"
                  },
                  "district": {
                    "type": "string"
                  },
                  "address": {
                    "type": "string"
                  },
                  "phone": {
                    "type": "string"
                  },
                  "wechat": {
                    "type": "string"
                  },
                  "wecomKf": {
                    "type": "string"
                  },
                  "intro": {
                    "type": "string"
                  },
                  "agent": {
                    "type": "string",
                    "description": "发起申请的 AI 标识"
                  },
                  "contact": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "申请成功，返回 slug 与 claimCode"
          },
          "409": {
            "description": "该 slug 已被已上线门店占用"
          },
          "429": {
            "description": "提交过于频繁"
          }
        }
      }
    },
    "/api/merchant": {
      "get": {
        "operationId": "getMyShop",
        "summary": "门店查自己的资料与审核状态",
        "parameters": [
          {
            "name": "slug",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-claim-code",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "店铺资料 + 状态"
          },
          "401": {
            "description": "缺少凭证"
          },
          "403": {
            "description": "凭证不对"
          },
          "404": {
            "description": "尚未申请入驻"
          }
        }
      },
      "put": {
        "operationId": "updateMyShop",
        "summary": "提交/更新门店资料（照片、产品价格、营业时间、可预约时段）",
        "description": "提交后进入平台审核；已上线门店的更新同样走复核。抽奖类玩法词与广告法绝对化用语会被直接拒绝（422）。",
        "parameters": [
          {
            "name": "slug",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-claim-code",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "已受理，等待审核"
          },
          "200": {
            "description": "已上线门店的更新已受理"
          },
          "422": {
            "description": "校验或合规不通过，返回 errors"
          }
        }
      }
    },
    "/api/merchant-list": {
      "get": {
        "operationId": "listMerchantStatus",
        "summary": "门店列表：公开视图只列已上线；带管理口令可看全部状态与待审",
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "列表"
          }
        }
      }
    },
    "/api/merchant-review": {
      "post": {
        "operationId": "reviewMerchant",
        "summary": "平台方审核：通过 / 打回 / 下架（需管理口令）",
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "slug",
                  "action"
                ],
                "properties": {
                  "slug": {
                    "type": "string"
                  },
                  "action": {
                    "type": "string",
                    "enum": [
                      "approve",
                      "reject",
                      "suspend",
                      "reopen"
                    ]
                  },
                  "note": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "状态已更新"
          }
        }
      }
    },
    "/api/export": {
      "get": {
        "operationId": "exportMerchants",
        "summary": "平台方导出已上线门店（供本地生成静态页发布，需管理口令）",
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "published"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "与 data/merchants.json 同构的商户数组"
          }
        }
      }
    },
    "/api/import": {
      "post": {
        "operationId": "importMerchants",
        "summary": "批量灌入门店数据（平台管理口令）",
        "description": "点评／抖音禁止爬取，平台也不抓。所以由 AI 或人工把门店资料整理成 JSON，从这里一次性灌入；灌入后所有 AI 都能从 /merchants.json 读到。",
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "merchants"
                ],
                "properties": {
                  "mode": {
                    "type": "string",
                    "enum": [
                      "merge",
                      "replace"
                    ],
                    "default": "merge"
                  },
                  "source": {
                    "type": "string",
                    "description": "数据来源留痕"
                  },
                  "merchants": {
                    "type": "array",
                    "items": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "逐条返回导入结果与 warnings"
          },
          "422": {
            "description": "全部校验失败，errors 里有原因"
          }
        }
      }
    },
    "/api/hold": {
      "post": {
        "operationId": "createHold",
        "summary": "占位（15 分钟，不产生承诺）· 阶段 3",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "slug",
                  "date",
                  "slot",
                  "party_size"
                ],
                "properties": {
                  "slug": {
                    "type": "string"
                  },
                  "date": {
                    "type": "string",
                    "format": "date"
                  },
                  "slot": {
                    "type": "string"
                  },
                  "party_size": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 20
                  },
                  "agent": {
                    "type": "string",
                    "description": "发起预约的 AI 助手标识"
                  },
                  "idempotency_key": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "hold_id"
          },
          "501": {
            "description": "阶段 3 尚未上线"
          }
        }
      }
    },
    "/api/confirm": {
      "post": {
        "operationId": "confirmBooking",
        "summary": "确认预约（必须落到真人手机验证码）· 阶段 3",
        "responses": {
          "200": {
            "description": "预约成功"
          },
          "501": {
            "description": "阶段 3 尚未上线"
          }
        }
      }
    },
    "/api/stats": {
      "get": {
        "operationId": "getStats",
        "summary": "平台浏览量（真人 / AI 调阅），需口令",
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "days",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 7
            }
          }
        ],
        "responses": {
          "200": {
            "description": "统计"
          },
          "401": {
            "description": "口令不对"
          }
        }
      }
    }
  },
  "x-agent-notes": [
    "价格、地址、电话以 /merchants.json 与门店页为准，缺失字段表示商户尚未确认。",
    "平台不代收款项，交易到店完成。",
    "平台不提供任何游戏、抽奖、积分或虚拟币玩法。",
    "AI 可以替主人查询与占位；确认预约必须经本人手机验证或门店人工确认。"
  ]
}