关于 salesforce-api
为通过 Salesforce REST API 执行常见数据操作提供操作指南与脚本的技能,面向需要查询和维护 Salesforce 记录的工作流。它涵盖 SOQL 分页、SOSL、记录读写、模式查询及 Composite 请求,并说明错误处理要点。
主要功能
- 01通过脚本执行 SOQL 并处理分页
- 02使用 SOSL 搜索记录
- 03读取、创建、更新与删除记录
- 04查询对象模式和字段权限
- 05组合多个请求并检查 API 限额
适用场景
- 01分页导出 Salesforce 查询结果
- 02按外部 ID 同步记录
- 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——这是最具体的信号。
400MALFORMED_QUERY— SOQL 语法错误。消息会指出出错的词元。400INVALID_FIELD,INVALID_TYPE— 字段或 sObject 名称错误,或不可见。运行 describe。自定义名称以__c结尾。400REQUIRED_FIELD_MISSING,FIELD_CUSTOM_VALIDATION_EXCEPTION— 缺少必填字段,或触发了验证规则。400STRING_TOO_LONG,INVALID_FIELD_FOR_INSERT_UPDATE— 值超出限制,或字段不可写——在 describe 中检查createable/updateable。401INVALID_SESSION_ID— 实例 URL 错误,或未配置凭据。先检查SALESFORCE_INSTANCE_URL;如果正确,请报告此问题。403INSUFFICIENT_ACCESS_OR_READONLY,API_DISABLED_FOR_ORG— 权限问题,或此用户/组织未启用 API。403REQUEST_LIMIT_EXCEEDED— 达到每日上限(等待 24 小时窗口重置),或达到并发长时间运行上限(退避后重试)。消息会说明是哪一种。404NOT_FOUND,ENTITY_IS_DELETED— ID 错误,或记录已删除。尝试使用queryAll。409ENTITY_IS_LOCKED— 记录被审批流程锁定。退避后重试。500UNKNOWN_EXCEPTION(通常是DUPLICATE_VALUE或触发器故障以 500 的形式返回) — 阅读消息。重试一次;如果问题仍然存在,请升级处理。503SERVER_UNAVAILABLE— 暂时性错误——服务过载或正在维护。退避后重试。
深入了解
references/api.md 提供了更完整的端点目录——完整的 SOQL/SOSL 语法参考、Composite Collections 和 Composite Tree、用于大规模数据加载的 Bulk API 2.0、describe global、记录计数、最近查看的记录、按记录类型获取选项列表值,以及关系遍历路径。需要使用上文未涵盖的端点或 SOQL 功能时,请阅读该文档。