开发者参考:REST API 与 MCP
完整的 Sellio API 参考:API 密钥认证、字段发现、REST 端点、错误格式、速率限制,以及供 AI 代理使用的 MCP 服务器。
通过 HTTP 集成 Sellio,或通过 MCP 连接你的 AI 代理。无论哪种方式,使用的都是同一个密钥、同一个租户范围和同一个速率限制。几分钟内即可发现任意对象的字段,并开始读写记录。
认证
每个请求都在 Authorization: Bearer 请求头中携带一个 API 密钥。该密钥标识所属租户,因此一切都会自动限定在该租户范围内。切勿在浏览器中暴露该密钥,只能在服务器端使用。你可以在“设置 → API 与开发者”中生成和撤销密钥。
curl -H "Authorization: Bearer sk_live_..." \
https://www.selliocrm.com/api/v1/objects密钥范围
在“设置 → API 与开发者”中生成密钥时,你可以选择它的范围。只给每个集成它所需要的访问权限。这些限制在 REST 和 MCP 中的作用方式相同,因为两个接口使用的是同一个密钥和同一套控制机制。
- 仅读取:该密钥可以读取数据,但不能创建、编辑或删除。它会阻止 REST 中的 POST、PATCH 和 DELETE,以及 MCP 中的 create_record、update_record 和 delete_record 工具。写入或删除尝试会返回 403 及 { "error": "errors.apiKeyReadOnly" }。
- 限定对象:选择该密钥可以访问的对象。范围之外的任何对象都会返回 403 及 { "error": "errors.apiKeyObjectDenied" }。对象列表(GET /api/v1/objects 及 list_objects 工具)已经按范围过滤;活动(/api/v1/activities)算作 activity 对象,只有 activity 在范围内时密钥才能访问。
- 允许删除:默认情况下,即使开启了写入权限,密钥也绝不会执行删除。生成密钥时你可以开启删除权限,以启用 DELETE /api/v1/{object}/{id} 及 MCP 的 delete_record 工具。没有该范围时,删除操作会返回 403 及 { "error": "errors.apiKeyDeleteDenied" }。删除是软删除:记录会进入回收站,可以恢复。
未设置任何范围的密钥(默认情况)对所有对象拥有完整的读写权限,与以前一样。在此变更之前创建的密钥会保留完整访问权限,直到你生成一个新的限定范围密钥为止。
OAuth 与已连接的应用
当第三方系统需要代表用户进行集成(而不是让客户粘贴管理员密钥)时,使用带 PKCE 的 OAuth 2.0 授权码流程。用户会看到一个包含所请求范围的同意屏幕,批准后应用会获得一个访问令牌,该令牌只能执行已被同意的操作。应用是经过审核的:开发者需要注册并发布应用才能获得 client_id 和 client_secret。
- 将用户重定向到 GET /api/oauth/authorize,携带 client_id、redirect_uri(与应用允许列表精确匹配)、scope、state 和 PKCE(code_challenge,code_challenge_method=S256)。PKCE 是必需的。
- 已登录的用户在同意屏幕上批准后,CRM 会带着 code 和相同的 state 重定向回来。
- 在你的服务器上,用该 code 到 POST /api/oauth/token 换取访问令牌(grant_type=authorization_code,需要 code_verifier、client_id、client_secret 和 redirect_uri),得到一个 Bearer 令牌(约 1 小时有效)和一个刷新令牌。
- 使用 Authorization: Bearer at_... 调用 v1 API 和 MCP 服务器,范围限定为已同意的内容。使用 grant_type=refresh_token 刷新;刷新令牌会被轮换(旧令牌使用后失效),重复使用会撤销整个令牌族。可通过 POST /api/oauth/revoke 撤销。
# 1) 同意授权(用户批准 → redirect_uri?code=...&state=...)
GET https://www.selliocrm.com/api/oauth/authorize?response_type=code&client_id=app_...&redirect_uri=https://your-app/callback&scope=records:read%20activities:read&state=abc&code_challenge=...&code_challenge_method=S256
# 2) 用授权码换取令牌(服务器端)
curl -X POST https://www.selliocrm.com/api/oauth/token \
-d grant_type=authorization_code -d code=<authcode> -d code_verifier=<verifier> \
-d client_id=app_... -d client_secret=secret_... -d redirect_uri=https://your-app/callback
# → { "access_token": "at_...", "token_type": "Bearer", "expires_in": 3600,
# "refresh_token": "rt_...", "scope": "records:read activities:read" }OAuth 范围:records:read 和 records:write(所有对象);records:read:contact 和 records:write:opportunity(按对象);activities:read 和 activities:write;objects:read(发现)。它们对应的读取、写入及按对象的执行方式与密钥相同。
嵌入式小组件(iframe)
你的应用可以在记录详情页或仪表盘上嵌入自己的界面(小组件)。该小组件运行在一个沙盒 iframe 中,由应用允许列表中你自己的域名提供服务,并请求 widgets:embed 范围。租户管理员在“应用 → 已安装”中选择每个小组件出现的位置。
宿主页面只通过 postMessage(sellio:widget:context,版本 1)向小组件发送界面上下文:recordId、objectApiName、locale、theme 和 installId。该消息中不包含任何业务数据、令牌或密钥。要读写数据,小组件需使用带有自己令牌(安装时授予的范围)的 OAuth API。小组件只能回复 sellio:widget:ready(用于重新获取上下文)和带 { height } 的 sellio:widget:resize(用于适配其高度,有上限);其他任何消息都会被忽略。
安全性:iframe 是沙盒化且跨源的,因此小组件无法访问宿主页面的 DOM 或 Cookie。宿主在每次 postMessage 时都会校验精确的来源(origin),embedUrl 也始终会与应用允许列表进行核对。在你的小组件中,只在 event.origin 等于宿主来源时才接受消息。
window.addEventListener('message', (event) => {
if (event.origin !== 'https://www.selliocrm.com') return; // 只信任宿主
const msg = event.data;
if (!msg || msg.version !== 1) return;
if (msg.type === 'sellio:widget:context') {
const { recordId, objectApiName, locale, theme } = msg.payload;
// 数据:使用你自己的令牌调用 OAuth API(该令牌绝不会通过 postMessage 传输)
}
});
parent.postMessage({ type: 'sellio:widget:ready', version: 1 }, 'https://www.selliocrm.com');字段发现
在创建或更新记录之前,先发现该对象的字段:有哪些字段、哪些是必填的,以及一个下拉选择字段接受哪些值。无需猜测,也不用去查看某条已有记录。
在 REST 中,你可以获取对象及其字段,包括 required、options(用于下拉选择)和 targetObject(用于查找关联):
GET https://www.selliocrm.com/api/v1/objects/contact
# → {
# "apiName": "contact",
# "label": "Contact",
# "fields": [
# { "apiName": "name", "label": "Name", "type": "text", "required": true },
# { "apiName": "email", "label": "Email", "type": "email", "required": false },
# { "apiName": "source", "label": "Source", "type": "select", "required": true,
# "options": [ { "value": "site", "label": "Website" },
# { "value": "referral", "label": "Referral" } ] },
# { "apiName": "company", "label": "Company", "type": "lookup",
# "required": false, "targetObject": "company" }
# ]
# }在 MCP 中,describe_object 工具会向代理返回相同的字段信息:
{ "method": "tools/call",
"params": { "name": "describe_object", "arguments": { "object": "contact" } } }REST API v1
任意对象的记录,以 JSON 格式收发。{object} 是 apiName(例如 contact、lead、opportunity),{id} 是记录的 uuid。
- GET /api/v1/objects:列出该租户的对象。
- GET /api/v1/objects/{object}:对象字段(发现)。
- GET /api/v1/{object}:列出并搜索记录。
- GET /api/v1/{object}/{id}:获取单条记录。
- POST /api/v1/{object}:创建一条记录。
- POST /api/v1/{object}/bulk:批量创建(最多 500 条;按条目部分成功)。
- PATCH /api/v1/{object}/{id}:更新字段(局部更新)。
- PATCH /api/v1/{object}/bulk:批量更新({ updates: [{ id, ...fields }] })。
- DELETE /api/v1/{object}/{id}:删除(软删除,进入回收站;需要密钥具有删除范围)。
列表参数(GET):limit(1 到 500,默认 50)、offset(分页偏移量,默认 0;不分页的总数在 total 字段中)、search(按名称搜索,不区分大小写和重音符号)、order(字段名加 :asc 或 :desc 表示排序)以及 filter。丰富过滤器:重复使用 filter=field:operator:value 可以用逻辑 AND 组合多个条件(不支持 OR;每次调用最多 12 个)。操作符:eq、neq、contains、gt、lt、gte、lte、empty、not_empty(empty 和 not_empty 不需要值)。旧的形式 filter=field:value(不带操作符)仍表示精确相等。
# 列表(limit、offset、search、filter、order)
curl -H "Authorization: Bearer sk_live_..." \
"https://www.selliocrm.com/api/v1/opportunity?limit=20&order=updated_at:desc&filter=stage:won"
# 丰富过滤器(逻辑 AND:amount >= 1000 且 stage = won)
curl -H "Authorization: Bearer sk_live_..." \
"https://www.selliocrm.com/api/v1/opportunity?filter=amount:gte:1000&filter=stage:eq:won"
# 单条记录
curl -H "Authorization: Bearer sk_live_..." \
https://www.selliocrm.com/api/v1/contact/8f3c...
# 创建
curl -X POST -H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{"name":"Ana Souza","email":"ana@acme.com","source":"site"}' \
https://www.selliocrm.com/api/v1/contact
# 批量创建(按条目部分成功)
curl -X POST -H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{"records":[{"name":"Ana"},{"name":"Bruno"}]}' \
https://www.selliocrm.com/api/v1/contact/bulk
# → { "results": [ { "index": 0, "ok": true, "id": "..." } ], "created": 1, "failed": 0 }
# 更新(局部更新)
curl -X PATCH -H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{"source":"referral"}' \
https://www.selliocrm.com/api/v1/contact/8f3c...
# 删除(软删除,进入回收站;需要密钥具有删除范围)
curl -X DELETE -H "Authorization: Bearer sk_live_..." \
https://www.selliocrm.com/api/v1/contact/8f3c...错误格式
错误以 { "error": "message" } 的 JSON 格式返回,并附带对应的 HTTP 状态码:
{ "error": "required field: source" } # HTTP 400- 200 和 201:成功(创建时为 201)。
- 400:校验或业务规则错误。
- 401:缺少密钥或密钥无效。
- 403:对该对象无权限(RBAC),或被密钥范围阻止(仅读取、对象不在范围内,或未启用删除)。
- 404:对象或记录未找到(包括对不存在 id 的 DELETE/PATCH)。
- 429:超出速率限制(参见 Retry-After 请求头)。
MCP 服务器(AI 代理)
Sellio 提供原生的 MCP(模型上下文协议)服务器,让你的 AI 代理能够安全地读写 CRM。使用的是同一个 API 密钥、同一个速率限制、同一套校验规则和同一套 RBAC。服务器地址为 https://www.selliocrm.com/api/mcp。
- list_objects:列出该租户的对象。
- describe_object:某个对象的字段(必填项、类型、选项)。
- list_records:列出并搜索记录。
- get_record:按 id 获取单条记录。
- create_record:创建一条记录。
- update_record:更新字段。
- delete_record:删除(软删除,进入回收站);需要密钥具有删除范围。
支持通过 HTTP 远程 MCP 的客户端,使用该地址并携带 Authorization: Bearer 请求头。在不支持原生远程 HTTP 的客户端上,使用 mcp-remote 桥接:
{
"mcpServers": {
"sellio-crm": {
"command": "npx",
"args": [
"-y", "mcp-remote",
"https://www.selliocrm.com/api/mcp",
"--header", "Authorization: Bearer sk_live_..."
]
}
}
}速率限制
每个密钥都有一个按分钟计的限制(默认 120,可配置)。响应中包含 X-RateLimit-Limit、X-RateLimit-Remaining 和 X-RateLimit-Reset 请求头。超出限制时,API 会返回 429 及 Retry-After。
对象模型
每个租户都有标准对象(联系人、公司、线索、商机等)和自定义的无代码对象。使用 GET /api/v1/objects 发现全部对象,使用 GET /api/v1/objects/{object} 或 describe_object 发现每个对象的字段。架构(schema)始终是你所属租户的架构。