关于 factorial-api-sdks
用于在 TypeScript、Python 和 Ruby 中使用 Factorial 官方 API SDK,并处理 Factorial Webhook 的 Skill。内容涵盖命名空间客户端、身份验证、分页、错误及类型化 Webhook 负载。
主要功能
- 01支持三种语言的官方 SDK
- 02API 密钥与 OAuth 身份验证
- 03按命名空间组织的端点客户端
- 04分页辅助功能
- 05类型化 Webhook 负载
适用场景
- 01调用 Factorial API 端点
- 02逐页获取大型数据集
- 03管理 Webhook 订阅
- 04处理并为 Webhook 事件定义类型
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ factorialco/ factorial-api-sdks --skill factorial-api-sdks安装后在 Claude Code 中输入/factorial-api-sdks确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
reference/ruby-methods.jsonsdk-methods.mdwebhooks.md详细介绍
Factorial API SDK
官方 SDK 使用带有领域命名空间的客户端、分页辅助工具和简洁的身份验证来封装 Factorial 公共 API。本指南将教 Agent 如何使用这些 SDK,以及如何处理 Factorial Webhook。生成的参考资料位于 reference/(参见参考资料)。
- TypeScript:
@factorialco/api-client(npm) - Python:
factorial-api-client(PyPI) - Ruby:
factorial_api(RubyGems)
安装
npm install @factorialco/api-client # TypeScript
pip install factorial-api-client # Python
gem install factorial_api # Ruby
身份验证
提供一个 API 密钥或 OAuth 令牌(也可以两者都提供):
| 选项 | 发送的标头 |
|---|---|
apiKey | x-api-key: <value> |
token | Authorization: Bearer <value> |
Factorial API 密钥采用 JWT 格式,但通过
x-api-key发送,而不是作为 Bearer 令牌发送。
可以显式传入凭据,也可以从环境变量中读取(FACTORIAL_API_KEY、FACTORIAL_TOKEN,以及可选的 FACTORIAL_BASE_URL)。
import { FactorialClient } from "@factorialco/api-client";
const client = new FactorialClient({ apiKey: process.env.FACTORIAL_API_KEY });
from factorial_api_client import FactorialClient
client = FactorialClient(api_key="YOUR_KEY") # or token="...", or from env
require "factorial_api"
api = F::Api.new(api_key: ENV["FACTORIAL_API_KEY"]) # or token:, or from env
调用端点
客户端按 client.<namespace>.<resource>.<method> 组织。命名空间和资源与 REST 路径 /api/<version>/resources/<namespace>/<resource> 对应。
方法命名规则明确:
| HTTP / 形态 | SDK 方法 |
|---|---|
GET 集合 | list() / paginate() / all() |
按 ID 执行 GET | get(id) |
POST 集合 | create(body) |
按 ID 执行 PUT/PATCH | update(id, body) |
按 ID 执行 DELETE | delete(id) |
自定义操作(如 apply) | 驼峰式操作名称,例如 apply() |
const { data } = await client.employees.employees.list();
const created = await client.apiPublic.webhookSubscriptions.create({ /* body */ });
employees = client.employees.employee.list()
sub = client.api_public.webhook_subscription.create(body={...})
Ruby 使用相同的结构,但采用 snake_case。必需参数(路径、查询或表单参数)均作为具名关键字传入;可选查询参数放入 query_params: 哈希中,请求体则通过 *_request 关键字传入。(底层的原始低级访问器,例如 api.employees_employee.employees_employees_get(true, false),仍可继续使用。)
employees = api.employees.employee.list(only_active: true, only_managers: false).data
team = api.teams.team.create(teams_teams_post_request: { name: "Platform" })
要查找任何端点对应的准确命名空间、资源和方法,请查阅 reference/sdk-methods.md(按组列出每个端点及其 TS 和 Ruby 调用方式),或参阅在线 API 参考。
分页
列表端点返回 { data: T[], meta: { end_cursor?, has_next_page, ... } }。
list()— 获取一页原始数据paginate()— 异步迭代器(TS)/ 同步或异步生成器(Python)all()(TS)/collect_all()(Python)— 获取所有页面并汇总到一个数组/列表中- Ruby:所有可列表资源都提供
paginate(惰性 Enumerator,可通过limit:/max_items:限制)和all;F::Api.paginate { |page| ... }用于封装原始调用
for await (const emp of client.employees.employees.paginate()) { /* ... */ }
const everyone = await client.employees.employees.all({ maxItems: 500 });
for emp in client.employees.employee.paginate(max_items=50): ...
everyone = client.employees.employee.all()
高容量检索
页面最多返回 100 项——这是服务端的硬性上限,并非默认值
(参见分页文档)。
传入更大的 limit 不会产生任何效果。游标分页按顺序进行(第 N+1 页需要第 N 页的 end_cursor),因此对大型数据集调用 all()(例如整整一个公司月的 attendance/worked_times)意味着需要顺序发送数十个请求。为合理控制请求数量和延迟:
- 先筛选。 使用端点的查询参数(日期范围、
ids、employee_ids等),而不是获取所有数据后再在本地筛选。 - 增量同步。 如果端点支持
updated_at一类的筛选条件,只获取自上次运行后发生变更的数据并在本地缓存—— 不要为每份报告重新获取整个数据集。 - 拆分大型请求。 将一个大型查询拆分为多个带筛选条件的子查询(按 日期范围或 ID 分块),并发运行——每个子查询仍需顺序分页,但总耗时会缩短。请求总数 不变,因此请留意速率限制。
- 设置防御性上限。 传入
max_items/maxItems,避免因错误或意外的数据量导致无限制抓取。
服务端没有聚合端点;总计值(例如每位员工在某个时段内的工时) 必须根据原始记录在客户端计算。
错误
所有 SDK 在收到非 2xx 响应(令牌错误或过期、基础 URL 错误、 服务器错误)时都会明确报错,而不会静默地返回空数据。每个 SDK 都会抛出包含状态码和响应正文的类型化 错误:
| SDK | 类 | 状态 | 正文 |
|---|---|---|---|
| TypeScript | FactorialApiError(扩展 Error) | status | body(已解析),以及 method、url |
| Python | UnexpectedStatus | status_code | content(字节) |
| Ruby | F::Api::ApiError | code | response_body |
// TypeScript — results have no `error` field; failures throw.
import { FactorialApiError } from "@factorialco/api-client";
try {
const { data } = await client.employees.employees.get({ path: { id: "42" } });
} catch (err) {
if (err instanceof FactorialApiError) console.error(err.status, err.url, err.body);
else throw err; // transport failure (DNS/connection), not an HTTP response
}
# Python
from factorial_api_client.generated.errors import UnexpectedStatus
try:
employees = client.employees.employees.list()
except UnexpectedStatus as e:
print(e.status_code, e.content)
# Ruby
begin
api.employees.employee.list
rescue F::Api::ApiError => e
puts e.code, e.response_body
end
API 版本管理
SDK 针对特定的 Factorial API 日期版本(例如 2026-04-01),并由 SDK 的主版本固定。
较新的 API 版本会随新的 SDK 主版本一同发布。
Webhook
Webhook 是 Factorial 在事件发生时发送到你的 target_url 的 HTTP POST 请求。
传递方式
- 为某个
subscription_type(例如ats/application/create)创建Webhook 订阅,指定target_url和你的company_id。 - 事件触发时,Factorial 会向
target_url发送POST。顶层负载就是资源对象—— 不会封装在{ type, data }信封中。如果需要轻松区分事件,请为每种事件使用不同的 URL。 - 如果订阅时设置了
challenge,Factorial 会通过x-factorial-wh-challenge请求标头原样返回该值,以便你验证来源。 - 可选的作者标头
x-factorial-author-id/x-factorial-author-type(employee或company)会标识触发事件的人,前提是安全可公开此信息。 - 重试策略:48 小时内最多重试 20 次;之后会禁用订阅并向你发送邮件。使用
PUT { enabled: true }重新启用。
通过 SDK 管理订阅
await client.apiPublic.webhookSubscriptions.create({
subscription_type: "ats/application/create",
target_url: "https://example.com/webhooks/factorial",
challenge: "a-secret-you-choose",
company_id: 55,
});
client.api_public.webhook_subscription.create(body={
"subscription_type": "ats/application/create",
"target_url": "https://example.com/webhooks/factorial",
"challenge": "a-secret-you-choose",
"company_id": 55,
})
为处理程序负载添加类型,使用导出的 webhook 类型:
import type { AtsApplicationCreateWebhook, WebhookPayloadMap, WebhookSubscriptionType }
from "@factorialco/api-client";
// Direct alias
function onApplicationCreated(payload: AtsApplicationCreateWebhook) { /* ... */ }
// Typed dispatch keyed on the runtime subscription_type
function handle<T extends WebhookSubscriptionType>(type: T, payload: WebhookPayloadMap[T]) { /* ... */ }
from factorial_api_client import AtsApplicationCreateWebhook, WEBHOOK_PAYLOAD_TYPES
def on_application_created(payload: AtsApplicationCreateWebhook) -> None: ...
# Runtime lookup of the model class for a subscription_type
model_cls = WEBHOOK_PAYLOAD_TYPES["ats/application/create"]
完整的事件列表、对应的 subscription_type 和负载字段见
reference/webhooks.md。
参考资料
生成的、特定于 SDK 的查阅表(请参阅以了解确切名称和结构):
reference/webhooks.md— 所有 Webhook 事件、对应的subscription_type和负载字段。reference/sdk-methods.md— 按命名空间/资源分组的所有 REST 端点,以及对应的 SDK 调用。
有关文字说明指南(OAuth 流程、API 密钥、版本管理、Webhook 策略等),请参阅 在线文档——内容始终为最新版本,此处不包含副本: