mcpField
S
salesforce-api

salesforce-api

github.com/anthropics营销与增长7439 次安装3 周前更新
代码仓库

关于 salesforce-api

为通过 Salesforce REST API 执行常见数据操作提供操作指南与脚本的技能,面向需要查询和维护 Salesforce 记录的工作流。它涵盖 SOQL 分页、SOSL、记录读写、模式查询及 Composite 请求,并说明错误处理要点。

主要功能

  1. 01通过脚本执行 SOQL 并处理分页
  2. 02使用 SOSL 搜索记录
  3. 03读取、创建、更新与删除记录
  4. 04查询对象模式和字段权限
  5. 05组合多个请求并检查 API 限额

适用场景

  1. 01分页导出 Salesforce 查询结果
  2. 02按外部 ID 同步记录
  3. 03检查字段与关系名称后构造查询

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/anthropics/claude-tag-plugins --skill salesforce-api

安装后在 Claude Code 中输入/salesforce-api确认已加载。

附带文件references/api.mdscripts/sf_query.sh

详细介绍

在 Salesforce 中,每个 org 都有自己的实例 URL(即其 My Domain),API 版本号位于路径中:

https://<your-org>.my.salesforce.com/services/data/vXX.0/...

需要注意的要点:

  • 错误以 JSON 数组形式返回,成功结果则以对象形式返回。 对每个 jq 投影都使用 if type == "array" then . else <projection> end 进行保护,否则错误响应体会导致筛选器崩溃,你将无法看到 errorCode。
  • 自定义对象和字段以 __c 结尾;自定义关系名称以 __r 结尾(在 SOQL 父级路径和子查询中使用 __r)。
  • 记录 ID 为 15 或 18 个字母数字字符。18 位形式不区分大小写,优先使用它。
  • SOQL 不支持 SELECT *。虽然有 FIELDS(ALL) / FIELDS(CUSTOM),但需要使用 LIMIT 200。
  • Describe 就是你的架构信息——包括字段名称、选项列表值、关系名称以及 createable/updateable 标志。猜测字段名称前先读取它。

请求设置

身份验证由运行时处理——凭据会注入发往此 API 的请求,因此无需进行任何设置。不要尝试创建、生成、刷新或验证令牌或密钥。凭据变量仅用于确保请求格式正确;如果某个变量未设置,请将其设为任意占位值。持续出现 401/403 表示此工作区尚未配置凭据——请报告这一情况,不要调试身份验证。

实例 URL 必须是真实有效的——每个 org 都有自己的实例 URL,且它是每个请求路径的一部分:

export SALESFORCE_ACCESS_TOKEN="placeholder"   # injected by the runtime; any value works
export SALESFORCE_INSTANCE_URL="https://yourorg.my.salesforce.com"
export SF_API="${SALESFORCE_INSTANCE_URL}/services/data/v66.0"

基本检查——确认实例 URL 正确,且工作区已正确配置:

curl -sS "${SF_API}/" -H "Authorization: Bearer ${SALESFORCE_ACCESS_TOKEN}" | jq .
# Returns a map of available API resources on success.

为简洁起见,以下示例使用了一个辅助函数。定义一次,或将 -H 标志添加到每个 curl 命令中:

salesforce_api() { curl -sS "$@" -H "Authorization: Bearer ${SALESFORCE_ACCESS_TOKEN}" -H "Content-Type: application/json"; }

核心操作

1. 运行 SOQL 查询(scripts/sf_query.sh)

通过捆绑脚本运行 SOQL(路径相对于此技能目录):脚本会提交查询、通过 nextRecordsUrl 获取所有分页结果、显示数组形式的错误响应体、移除每条记录都带有的 attributes 封装,并将嵌套的父级关系对象展平为点分隔键列(Account.Name)。

scripts/sf_query.sh \
  "SELECT Id, Name, Amount, StageName, Account.Name FROM Opportunity
   WHERE CloseDate = THIS_QUARTER ORDER BY Amount DESC" \
  --max-rows 0
  • SOQL 可以作为一个带引号的参数传入,也可以通过 stdin 输入。实例相关配置来自上文的 SALESFORCE_INSTANCE_URL / SALESFORCE_ACCESS_TOKEN;--instance-url 和 --api-version 可覆盖这些配置。完整 SOQL 语法(父级路径、子查询、日期字面量、转义):参见 references/api.md 的 SOQL 部分。
  • --all 切换到 /queryAll(包括已删除/已归档的记录)。
  • --max-rows N 限制获取的行数(默认 10000,0 = 全部);--batch-size N(200–2000)设置 Sforce-Query-Options 分页大小;--json 将每行输出为一个 JSON 对象,而不是带表头的 TSV。totalSize 和行数输出到 stderr。
  • 退出代码:0 表示成功;非零表示失败(1 = API/参数错误,stderr 中包含 errorCode;其他值 = curl 传输错误)。

如果脚本报错,请阅读脚本——它只使用 curl + jq——并对照 references/api.md 调试。 SOSL 搜索、sObject 写入、Describe、Composite 和 Bulk API 2.0 都使用独立端点(参见下文操作和 references/api.md)。

2. 全文搜索(SOSL)

salesforce_api -G "${SF_API}/search" --data-urlencode "q=FIND {Acme} IN NAME FIELDS RETURNING Account(Id, Name), Contact(Id, Name, Email)" → 结果位于 .searchRecords 下(-G 会让 --data-urlencode 使用 GET;不加它时 curl 会发送 POST,而 /search 会拒绝该请求)。或者使用 GET /parameterizedSearch?q=Acme&sobject=Account&Account.fields=Id,Name。

3. 读取 / 创建 / 更新 / 删除一条记录
  • 读取 — GET ${SF_API}/sobjects/Account/ID?fields=Id,Name,Industry。省略 fields 可获取全部字段。父级字段需要使用 SOQL 或 /sobjects/Account/ID/Owner。按外部 ID 查询:/sobjects/Account/Ext_Id__c/VALUE。
  • 创建 — POST ${SF_API}/sobjects/Account,请求体为 {"Name":"Acme",...}。返回 {"id","success":true,"errors":[]}。查找关系:"AccountId":"001...",或按外部 ID 指定:"Account":{"Ext_Id__c":"ACME-42"}。
  • 更新 — PATCH ${SF_API}/sobjects/Opportunity/ID,请求体为 {"StageName":"..."}。返回 204 No Content(空响应体)——传入 -w '\n%{http_code}\n' 查看状态码。
  • 删除 — DELETE ${SF_API}/sobjects/Account/ID。成功时返回 204。记录会进入回收站约 15 天;删除操作可能沿主从关系级联——请确认意图。
4. 按外部 ID 执行 Upsert

对外部 ID 路径执行 PATCH,即可通过一次调用创建或更新记录——这是从其他系统同步数据最安全的方式:

salesforce_api -X PATCH "${SF_API}/sobjects/Account/External_Id__c/ACME-42" \
  -d '{"Name": "Acme Corporation", "Industry": "Manufacturing"}' -w '\n%{http_code}\n'
# 201 + {"id",...,"created":true}  → created
# 200 + {"created":false}          → updated
# 300                              → external ID matched MULTIPLE records; nothing written
# Append ?updateOnly=true to update-or-fail instead of update-or-create.
5. 描述 sObject(架构)

列出所有 sObject:GET ${SF_API}/sobjects → .sobjects[] | {name, label, custom, queryable}。

一个 sObject 的完整架构:

salesforce_api "${SF_API}/sobjects/Opportunity/describe" | \
  jq '{fields: [.fields[]? | {name, type, createable, updateable, picklistValues: [.picklistValues[]?.value]}], childRelationships: [.childRelationships[]? | {relationshipName, childSObject}]}'
6. Composite:在一个请求中执行多个操作

一次往返最多串联 25 个子请求。后续子请求可通过 @{refName.field} 引用先前的结果。设置 allOrNone: true 可在任何操作失败时回滚整个批次。每个子请求的 url 都是绝对路径,必须重复外层请求使用的 API 版本——如果更改了 ${SF_API} 中的 v66.0,此处也要相应更改。

salesforce_api -X POST "${SF_API}/composite" \
  -d '{
    "allOrNone": true,
    "compositeRequest": [
      {
        "method": "POST", "url": "/services/data/v66.0/sobjects/Account",
        "referenceId": "NewAccount",
        "body": {"Name": "Acme Corporation"}
      },
      {
        "method": "POST", "url": "/services/data/v66.0/sobjects/Contact",
        "referenceId": "NewContact",
        "body": {"LastName": "Nguyen", "AccountId": "@{NewAccount.id}"}
      },
      {
        "method": "GET", "url": "/services/data/v66.0/sobjects/Account/@{NewAccount.id}?fields=Id,Name",
        "referenceId": "ReadBack"
      }
    ]
  }' | jq '.compositeResponse[]? | {ref: .referenceId, status: .httpStatusCode, body: .body}'

即使子请求失败,外层请求仍会返回 200——请始终检查每个子请求的 httpStatusCode。对于没有交叉引用的大批量插入 / 更新,请使用 Composite Collections——POST /composite/sobjects,最多支持 200 条记录(参见 references/api.md)。

7. 检查限制

GET ${SF_API}/limits → .DailyApiRequests 显示 Max 和 Remaining。运行循环前请先检查——每个组织都有每 24 小时的调用上限。

分页

SOQL 响应每页最多返回 2000 条记录(可通过请求头 Sforce-Query-Options: batchSize=N 配置,范围为 200–2000)。如果还有更多记录,响应中会包含 done: false 和 nextRecordsUrl——这是一个相对于实例的路径,可通过 ${SALESFORCE_INSTANCE_URL} 执行 GET;scripts/sf_query.sh 会自动跟进该路径。SOQL 中的 OFFSET 上限为 2000——深度分页请使用 nextRecordsUrl,导出大量数据请使用 Bulk API 2.0(references/api.md)。

速率限制

Salesforce 会限制每个组织在滚动 24 小时内的 API 调用总数(而非每秒调用数)。每个响应都包含:

Sforce-Limit-Info: api-usage=1234/100000

达到上限后,会返回 403 和 errorCode: REQUEST_LIMIT_EXCEEDED。不会返回 Retry-After——请等待调用记录移出 24 小时窗口。此外还有单独的限制:最多同时执行 25 个长时间运行的请求(≥20s;Developer Edition 中为 5 个)。超出限制同样会返回 REQUEST_LIMIT_EXCEEDED(消息中会提及 ConcurrentRequests / ConcurrentPerOrgLongTxn),待正在执行的请求完成后限制即会解除——请退避后重试。请节制使用:通过 Composite 批量处理,仅选择所需字段,并优先使用 upsert,而非先读取再写入。

错误处理

错误是一个 JSON 数组:[{"message": "...", "errorCode": "...", "fields": [...]}]。优先查看 errorCode——这是最具体的信号。

  • 400 MALFORMED_QUERY — SOQL 语法错误。消息会指出出错的词元。
  • 400 INVALID_FIELD, INVALID_TYPE — 字段或 sObject 名称错误,或不可见。运行 describe。自定义名称以 __c 结尾。
  • 400 REQUIRED_FIELD_MISSING, FIELD_CUSTOM_VALIDATION_EXCEPTION — 缺少必填字段,或触发了验证规则。
  • 400 STRING_TOO_LONG, INVALID_FIELD_FOR_INSERT_UPDATE — 值超出限制,或字段不可写——在 describe 中检查 createable/updateable。
  • 401 INVALID_SESSION_ID — 实例 URL 错误,或未配置凭据。先检查 SALESFORCE_INSTANCE_URL;如果正确,请报告此问题。
  • 403 INSUFFICIENT_ACCESS_OR_READONLY, API_DISABLED_FOR_ORG — 权限问题,或此用户/组织未启用 API。
  • 403 REQUEST_LIMIT_EXCEEDED — 达到每日上限(等待 24 小时窗口重置),或达到并发长时间运行上限(退避后重试)。消息会说明是哪一种。
  • 404 NOT_FOUND, ENTITY_IS_DELETED — ID 错误,或记录已删除。尝试使用 queryAll。
  • 409 ENTITY_IS_LOCKED — 记录被审批流程锁定。退避后重试。
  • 500 UNKNOWN_EXCEPTION(通常是 DUPLICATE_VALUE 或触发器故障以 500 的形式返回) — 阅读消息。重试一次;如果问题仍然存在,请升级处理。
  • 503 SERVER_UNAVAILABLE — 暂时性错误——服务过载或正在维护。退避后重试。

深入了解

references/api.md 提供了更完整的端点目录——完整的 SOQL/SOSL 语法参考、Composite Collections 和 Composite Tree、用于大规模数据加载的 Bulk API 2.0、describe global、记录计数、最近查看的记录、按记录类型获取选项列表值,以及关系遍历路径。需要使用上文未涵盖的端点或 SOQL 功能时,请阅读该文档。

评论

支持 Markdown