SDK
AppForges 官方 TypeScript、Python、Go SDK 与 OpenAPI 规范。
TypeScript SDK
@appforges/sdk@v0.59.4由 sdk-gen 流水线从 OpenAPI 规范自动生成的官方 SDK:零运行时依赖、ESM + CJS 双格式、类型化错误、游标分页迭代器与 SSE 流式开箱即用。响应字段与 wire 完全一致(snake_case),无需任何转换。
安装
npm i @appforges/sdk
# or
bun add @appforges/sdk快速开始
import { AppForges } from "@appforges/sdk";
import { BearerAuth } from "@appforges/sdk/runtime/auth/bearer";
const client = new AppForges({
auth: new BearerAuth(process.env.APPFORGES_ACCESS_TOKEN!),
});
// Response fields are wire-faithful (snake_case) — payloads pass through.
const profile = await client.users.getProfile();
console.log(profile.user_id, profile.phone_number);分页迭代
// Cursor-paginated list methods return a Paginator:
for await (const page of client.pinpagePages.listPages(profile.user_id, { query: { pageSize: 50 } })) {
// ...one item at a time
}
// or collect everything:
const all = await client.pinpagePages.listPages(profile.user_id).all();错误处理
import { AppForgesError } from "@appforges/sdk/runtime/errors";
try {
await client.users.getProfile();
} catch (error) {
if (error instanceof AppForgesError) {
console.error(error.httpStatus, error.requestId, error.retryAfterMs);
}
}AppForgesError 携带 httpStatus / requestId / retryAfterMs;可结合 reason 与 traceId 定位请求。
Python SDK
appforges@0.59.4Python 3.11+,提供同步与异步客户端、严格 pydantic 模型、OAuth、类型化错误、游标分页与 SSE。响应字段保持 snake_case;使用 httpx 与 pydantic v2。
安装
pip install appforges==0.59.4同步客户端
import os
from appforges import AppForges, BearerAuth
with AppForges(auth=BearerAuth(os.environ["APPFORGES_ACCESS_TOKEN"])) as client:
profile = client.users.get_profile()
print(profile.user_id)异步客户端
import asyncio
import os
from appforges import AsyncAppForges, BearerAuth
async def main() -> None:
async with AsyncAppForges(auth=BearerAuth(os.environ["APPFORGES_ACCESS_TOKEN"])) as client:
profile = await client.users.get_profile()
print(profile.user_id)
asyncio.run(main())用户资料接口需要代表用户的 OAuth access token。测试环境设置 base_url="https://api-staging.appforges.com";with / async with 会关闭客户端拥有的连接。
SSE 流式响应
当 API 声明 SSE 时,可通过同步 for 或异步 async for 逐条读取事件。当前公开规格未声明 SSE 接口,因此暂无可调用的端点示例。
分页迭代
with AppForges(auth=BearerAuth(os.environ["APPFORGES_ACCESS_TOKEN"])) as client:
profile = client.users.get_profile()
for page in client.pinpage_pages.list_pages_all(profile.user_id, page_size=50, max_pages=10):
print(page.page_id)
# AsyncAppForges exposes the same iterator through async for.错误处理
from appforges import APIError, RateLimitExceededError
with AppForges(auth=BearerAuth(os.environ["APPFORGES_ACCESS_TOKEN"])) as client:
try:
client.users.get_profile()
except RateLimitExceededError as error:
print(error.retry_after) # seconds
except APIError as error:
print(error.http_status, error.reason, error.request_id, error.trace_id)默认最多重试 2 次,遵守 Retry-After;写请求仅按幂等约定重试。APIError 保留状态码、reason、request_id 与 trace_id。未提供的字段不发送;只有可空字段接受显式 None。
Go SDK
appforges-sdk-go@v0.59.4Go 1.23+,仅使用标准库,无第三方运行时依赖。提供 context 取消、严格模型、OAuth、类型化错误、游标分页与 SSE;JSON 字段保持 snake_case。
安装
go get github.com/appforges/appforges-sdk-go@v0.59.4快速开始
package main
import (
"context"
"fmt"
"os"
"time"
appforges "github.com/appforges/appforges-sdk-go"
"github.com/appforges/appforges-sdk-go/runtime"
)
func main() {
client, err := appforges.NewClient(runtime.WithBearerToken(os.Getenv("APPFORGES_ACCESS_TOKEN")))
if err != nil { panic(err) }
defer client.Close()
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
profile, err := client.Users.GetProfile(ctx)
if err != nil { panic(err) }
fmt.Println(runtime.Value(profile.UserId))
}用户资料接口需要代表用户的 OAuth access token。测试环境使用 runtime.WithBaseURL("https://api-staging.appforges.com");Close 释放客户端拥有的空闲连接。
分页迭代
for page, err := range client.PinpagePages.ListPagesAll(ctx, appforges.PinpagePagesListPagesParams{
UserId: runtime.Value(profile.UserId),
PageSize: runtime.Some[int64](50),
}) {
if err != nil { return err }
fmt.Println(runtime.Value(page.PageId))
// break stops fetching further pages.
}错误处理
import "errors"
var limited *appforges.RateLimitExceededError
var apiError *appforges.APIError
if errors.As(err, &limited) {
fmt.Println(limited.RetryAfter)
} else if errors.As(err, &apiError) {
fmt.Println(apiError.StatusCode, apiError.Reason, apiError.RequestID, apiError.TraceID)
}默认最多重试 2 次,遵守 Retry-After;写请求按幂等约定重试。errors.As 可取得状态码、reason、request_id 与 trace_id。Optional[T] 使用 Some / Null 区分值、未提供和可空字段的显式 null。
SSE 流式响应
声明 SSE 的 API 返回 iter.Seq2;break 或 context 取消会关闭响应连接。当前公开规格未声明 SSE 端点,暂无真实端点示例。
文件数据与 Webhook 校验
encodeUploadData / encode_upload_data / EncodeUploadData 将小于 4 MiB 的二进制数据转为公开 UploadAsset 接口的 JSON base64 字段。helper 本身不发请求;预签名上传流程当前未公开。
TypeScript
import { encodeUploadData } from "@appforges/sdk/runtime/upload";
import { verifyWebhookSignature } from "@appforges/sdk/runtime/webhook";
const data = encodeUploadData(new Uint8Array([0, 255]));
// Pass data to the generated UploadAsset request body.
async function verifyRequest(request: Request, originalSecret: string) {
const body = new Uint8Array(await request.arrayBuffer());
const signature = request.headers.get("X-Webhook-Signature") ?? "";
return verifyWebhookSignature(body, signature, [originalSecret]);
}Python
from appforges import encode_upload_data, verify_webhook_signature
data = encode_upload_data(bytes([0, 255]))
def verify_request(raw_body: bytes, signature: str, original_secret: str) -> bool:
return verify_webhook_signature(raw_body, signature, [original_secret])Go
import "github.com/appforges/appforges-sdk-go/runtime"
func encodeFile(data []byte) (string, error) {
return runtime.EncodeUploadData(data)
}
func verifyRequest(rawBody []byte, signature, originalSecret string) bool {
return runtime.VerifyWebhookSignature(rawBody, signature, []string{originalSecret})
}校验 X-Webhook-Signature 时,使用解析 JSON 之前的原始 body 字节和创建或轮换时返回的原始 secret;多个本地 secret 可用于轮换过渡。当前协议不提供防重放,也不认证 X-Webhook-Event。
SDK 发布包含 API 兼容性检查及自动 CHANGELOG。模型、字段和方法描述随 OpenAPI 同步至各语言文档。
OpenAPI 规格
想自己生成客户端?下载 OpenAPI 3.1 规格文件,喂进你常用的 generator。
当前版本 v0.59.4,每次平台发版后重建。
版本策略
客户端实际说话的 wire schema 由 API-Version API-Version 升级与版本 header 单独控制。