API + MCP / SCHEMA 0.1
给 Agent 一份
有依据的数据。
先查看公开 mock 演示,再用获邀签发的 API Key 接入真实数据。示例不会在本页执行,也不会收集你的密钥。
试用与鉴权
当前采用邀请制,由项目团队人工签发和撤销应用密钥。请通过与你对接的团队成员申请;暂无在线注册或支付流程。
在服务端使用 Authorization: Bearer <API_KEY>。不要把密钥放进浏览器代码、公开仓库、查询参数或 NEXT_PUBLIC_* 环境变量。
默认每应用每天 1,000 次、每分钟 30 次调用;REST 与 MCP 共享 UTC 固定窗口配额。MCP 的工具调用计入配额,初始化和工具列表不计入。试用阶段不收取在线支付。
REST API
/v1/places按名称、地区、类别、距离及设施查询
/v1/places/{id}门店详情、依据、时效与模块覆盖
/v1/places/{id}/menu菜单规格、观测价格及价格条件
/v1/places/{id}/offers套餐内容、售卖方案及使用规则
/v1/coverage已发布覆盖、模块完整率与更新时间
/mcp与 REST 共用数据、权限和配额的工具调用
结构化筛选
q 按名称匹配;country 为 CN 或 SG 等国家代码;city、category 按已发布值筛选。parking、private_room、children_facilities、pets 接受 available、unavailable、conditional,仅匹配有效且无冲突的依据。
距离查询同时提供 lat、lon、radius_km(最多 50 公里),只匹配已确认 WGS84 坐标。默认每页 20 条,per_page 最大 100;page 从 1 开始。fields 为逗号分隔字段名,稳定 ID、来源和模块状态始终保留。
首版没有任意自然语言查询、套餐资格判断、预订、库存或交易接口。
从一次查询开始
Python · 在服务端运行
import json, os
from urllib.request import Request, urlopen
base = os.environ.get("O2O_API_BASE_URL", "https://api.o2o.dev")
request = Request(
base + "/v1/places?country=CN&category=restaurant&per_page=5",
headers={"Authorization": "Bearer " + os.environ["O2O_API_KEY"]},
)
with urlopen(request, timeout=15) as response:
print(json.load(response))JavaScript · Node.js
const base = process.env.O2O_API_BASE_URL || "https://api.o2o.dev";
const response = await fetch(base + "/v1/places?country=SG", {
headers: { Authorization: `Bearer ${process.env.O2O_API_KEY}` },
signal: AbortSignal.timeout(15_000),
});
if (!response.ok) throw new Error(`o2o: ${response.status}`);
const { data, meta } = await response.json();
console.log(data, meta);MCP 工具
将远程 HTTP MCP 地址配置为 https://api.o2o.dev/mcp,并通过客户端支持的安全密钥配置传入 Bearer 请求头。不同客户端的配置格式不同,下方是协议请求示例,不是通用客户端配置文件。
POST https://api.o2o.dev/mcp
Authorization: Bearer <API_KEY>
Content-Type: application/json
Accept: application/json, text/event-stream
{"jsonrpc":"2.0","id":1,"method":"initialize",
"params":{"protocolVersion":"2025-06-18",
"capabilities":{},"clientInfo":{"name":"your-agent","version":"1.0"}}}初始化后发送 notifications/initialized,再调用 tools/list 或 tools/call。支持 2025-03-26 和 2025-06-18;采用无状态 HTTP JSON 响应,不提供 SSE 流或会话。
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "search_places",
"arguments": {
"country": "CN",
"private_room": "available",
"per_page": 5
}
}
}工具:search_places、get_place、get_menu、get_offers、get_coverage。详情工具使用 id 参数;搜索参数与 REST 一致。
读懂数据,而不只读到数据
- 稳定身份
- 门店 ID 不随名称变化;品牌、门店和平台外部 ID 分开记录。
- 来源与依据
- evidence 记录字段依据、observed_at、valid_until、verification 和 conflict;sources 提供可公开的来源归属。原始私有材料不会公开。
- 未知与缺失
- unknown 不等于 false。门店存在但没有菜单返回 200、data: []、meta.status: missing;不存在的门店返回 404。
- 价格语义
- 金额为十进制字符串,附币种、单位和适用条件。优惠价格不代表所有用户可购买;未提供的费用不能默认为零。
- 时间与冲突
- 采用门店当地时区,区分观测时间与有效期。默认复核周期:地址和联系方式 90 天,营业时间与设施 30 天,菜单价格 7 天。来源明确期限可缩短周期。
- 深度档案
- 菜单、有效且已确认的营业时间,加至少两项有效且已确认的设施信息。不代表所有字段齐全。
- 授权范围
- 只分发已核准许可的数据。对来源撤销授权、过期和冲突持续做显式标记;不从菜单或店名推断过敏原安全。
错误与安全重试
400参数不合法检查字段名、分页和参数类型。
401鉴权失败检查密钥是否有效或已撤销。
403来源请求被拒绝浏览器 Origin 需显式允许;优先服务端调用。
404门店不存在不要将它等同于某个模块缺失。
429配额已用完等待下一配额窗口,避免立即循环重试。
遇到 5xx 或网络超时采用有上限的指数退避。集成日志不要记录 API Key、完整搜索正文或精确用户坐标。