Skip to content

API 参考

本文档提供 Lovrabet OpenAPI 所有接口的完整参考,包括 SDK 用法和底层 HTTP 规范。

基础信息

环境地址

环境域名
生产环境https://runtime.lovrabet.com

请求规范

  • 请求方法: 所有接口统一使用 POST
  • 内容类型: application/json
  • 字符编码: UTF-8
  • 超时设置: 建议设置 30 秒超时

认证方式

所有请求需要在 HTTP Header 中包含以下认证信息:

Header 名称说明示例
X-Time-Stamp时间戳(毫秒)1758903130713
X-App-Code应用编码app-c2dd52a2
X-Dataset-Code数据集编码(部分接口需要)0fefba76fe29...ff
X-Token签名 TokenjdqqGtzecF2I6FIW...

TIP

使用 SDKSDK 会自动添加所有必需的请求头,无需手动处理。

OpenAPI 接口列表

完整接口清单

以下是 Lovrabet OpenAPI 提供的所有接口及其详细信息:

接口名称HTTP 方法完整 URL 路径SDK 方法功能说明
批量查询数据POST/openapi/data/get-listfilter(params)分页查询数据,支持筛选、排序
查询单条数据POST/openapi/data/get-onegetOne(id)根据 ID 获取单条数据详情
创建数据POST/openapi/data/createcreate(data)创建新的数据记录
更新数据POST/openapi/data/updateupdate(id, data)更新已有数据记录
执行 SQLPOST/api/custom/executeSqlsql.execute(options)执行自定义 SQL 查询

INFO

功能限制OpenAPI 目前暂不支持 delete()getSelectOptions()excelExport() 操作。如需使用这些功能,请使用基于 Cookie 认证的 WebAPI 模式。

请求参数规范

所有 OpenAPI 接口的请求体都遵循以下结构:

TypeScript
{
  appCode: string;           // 应用编码(所有接口必需)
  datasetCode: string;       // 数据集编码(所有数据操作接口都需要)
  paramMap: {                // 业务参数对象
    // 具体参数根据不同接口而定
  }
}

认证信息传递方式:

  • OpenAPI 的认证信息(不在请求体中),而是通过 HTTP Headers 传递:

    • X-Time-Stamp: 时间戳
    • X-App-Code: 应用编码
    • X-Dataset-Code: 数据集编码
    • X-Token: 签名 Token
  • SDK 会自动处理这些 Headers,开发者无需手动添加

各接口参数详解

1. 批量查询数据 (getList)

URL: POST /openapi/data/get-list

请求体参数:

TypeScript
{
  appCode: string;
  datasetCode: string;
  paramMap: {
    currentPage?: number;     // 当前页码,从 1 开始
    pageSize?: number;        // 每页条数
    ytSortList?: SortList;    // 排序配置(通过 SDK 的 sortList 参数自动添加)
    [key: string]: any;       // 其他查询条件(根据数据集字段)
  }
}

参数说明:

参数名类型必填默认值说明
appCodestring✅ 是-应用编码
datasetCodestring✅ 是-数据集编码
paramMap.currentPagenumber❌ 否1当前页码,从 1 开始
paramMap.pageSizenumber❌ 否20每页记录数,最大 100
paramMap.ytSortListSortList❌ 否-排序配置数组,由 SDK 的 sortList 参数自动生成
paramMap.[字段名]any❌ 否-其他查询条件,根据数据集实际字段定义

查询条件示例:

根据数据集的不同字段,可以使用以下查询模式:

TypeScript
{
  // 精确匹配
  status: "active",
  customer_type: "vip",

  // 模糊查询(字段名加 _like 后缀)
  name_like: "张",

  // 范围查询(字段名加 _start/_end 后缀)
  create_time_start: "2024-01-01",
  create_time_end: "2024-12-31",
  amount_start: 1000,
  amount_end: 5000,

  // IN 查询(字段名加 _in 后缀,值为数组)
  status_in: ["active", "pending"],

  // IS NULL 查询(字段名加 _is_null 后缀)
  deleted_at_is_null: true,
}

排序功能 (ytSortList):

OpenAPI 使用 ytSortList 字段进行排序,通过 SDK 的 sortList 参数传入:

TypeScript
import { SortOrder } from "@lovrabet/sdk";

// SDK 调用方式(推荐)
const result = await client.models.users.filter(
  { currentPage: 1, pageSize: 20 },
  [
    { priority: SortOrder.DESC }, // 优先级降序
    { createTime: SortOrder.DESC }, // 创建时间降序
    { name: SortOrder.ASC }, // 名称升序
  ]
);

// SDK 会自动将 sortList 转换为 ytSortList 字段放到 paramMap 中
// 实际请求体: { appCode, datasetCode, paramMap: { ytSortList: [...] } }

TIP

排序说明

  • OpenAPI 只支持通过 ytSortList 字段排序
  • 使用 SDK 时,通过 getList() 方法的第二个参数 sortList 传入排序配置
  • SDK 会自动将 sortList 转换为 ytSortList 格式

响应数据 (data 字段):

TypeScript
{
  paging: {
    pageSize: number; // 每页记录数
    totalCount: number; // 总记录数
    currentPage: number; // 当前页码
  }
  tableData: Array<T>; // 数据列表数组
  tableColumns: Array<{
    title: string; // 列标题
    dataIndex: string; // 字段名
  }>;
}

2. 查询单条数据 (getOne)

URL: POST /openapi/data/get-one

请求体参数:

TypeScript
{
  appCode: string;
  datasetCode: string;
  paramMap: {
    id: string | number; // 记录 ID
  }
}

参数说明:

参数名类型必填说明
appCodestring✅ 是应用编码
datasetCodestring✅ 是数据集编码
paramMap.idstring/number✅ 是要查询的记录 ID

响应数据 (data 字段):

TypeScript
{
  id: string | number;     // 记录 ID
  [key: string]: any;      // 其他字段根据数据集定义
}

3. 创建数据 (create)

URL: POST /openapi/data/create

请求体参数:

TypeScript
{
  appCode: string;
  datasetCode: string;
  paramMap: {
    [key: string]: any;   // 要创建的数据字段
  }
}

参数说明:

参数名类型必填说明
appCodestring✅ 是应用编码
datasetCodestring✅ 是数据集编码
paramMap.[字段名]any根据字段定义要创建的数据,字段和必填性根据数据集定义

注意事项:

  • 系统字段(如 id, gmt_create, gmt_modified)会自动生成,无需传入
  • 必填字段必须提供,否则会返回参数错误
  • 字段类型需要与数据集定义一致

响应数据 (data 字段):

TypeScript
{
  id: string | number;     // 新创建记录的 ID
  [key: string]: any;      // 完整的记录数据(包括自动生成的字段)
}

4. 更新数据 (update)

URL: POST /openapi/data/update

请求体参数:

TypeScript
{
  appCode: string;
  datasetCode: string;
  paramMap: {
    id: string | number;  // 要更新的记录 ID
    [key: string]: any;   // 要更新的字段
  }
}

参数说明:

参数名类型必填说明
appCodestring✅ 是应用编码
datasetCodestring✅ 是数据集编码
paramMap.idstring/number✅ 是要更新的记录 ID
paramMap.[字段名]any❌ 否要更新的字段,只需传入需要更新的字段即可(部分更新)

注意事项:

  • 支持部分更新,只需传入要修改的字段
  • gmt_modified 字段会自动更新
  • 不能修改 idgmt_create 字段

响应数据 (data 字段):

TypeScript
{
  id: string | number;     // 记录 ID
  [key: string]: any;      // 完整的更新后记录数据
}

响应结构

通用响应格式

所有接口响应都包含以下顶层字段(由平台网关返回):

TypeScript
{
  success: boolean;      // 请求是否成功
  msg: string;           // 响应消息
  data: any;             // 响应数据
  errorCode?: number;    // 错误码(失败时返回)
  errorMsg?: string;     // 错误信息(失败时返回)
}

getList 响应的固定字段

getList 接口的 data 字段包含以下三个固定字段(SDK 返回结构与平台一致):

TypeScript
{
  paging: {
    // 【固定字段】分页信息
    pageSize: number; // 每页记录数
    totalCount: number; // 总记录数
    currentPage: number; // 当前页码
  }
  tableData: Array<T>; // 【固定字段】数据列表数组
  tableColumns: Array<{
    // 【固定字段】表格列定义
    title: string; // 列标题
    dataIndex: string; // 字段名
  }>;
}

SDK 使用

创建客户端

TypeScript
import { createClient } from "@lovrabet/sdk";

const client = createClient({
  appCode: "your-app-code",
  accessKey: process.env.LOVRABET_ACCESS_KEY,
  models: {
    users: {
      tableName: "users",
      datasetCode: "your-dataset-code",
    },
  },
});

SDK 方法列表

每个模型实例都提供以下方法:

方法说明对应 API
getList(params?)批量查询数据/openapi/data/get-list
getOne(id)查询单条数据/openapi/data/get-one
create(data)新增单条数据/openapi/data/create
update(id, data)更新单条数据/openapi/data/update

SQL 执行

OpenAPI 模式支持执行自定义 SQL 查询,适用于复杂报表、多表关联等场景。

基本用法

TypeScript
// 执行 SQL 查询
const result = await client.sql.execute({
  sqlCode: 'your-sql-code',  // SQL 代码标识
  params: {                  // 可选:SQL 参数
    startDate: '2024-01-01',
    endDate: '2024-12-31'
  }
});

// 检查执行结果
if (result.execSuccess) {
  console.log('查询结果:', result.execResult);
} else {
  console.error('执行失败:', result.execError);
}

带类型安全的调用

TypeScript
interface MonthlyStats {
  customer_name: string;
  total_amount: number;
  order_count: number;
}

const result = await client.sql.execute<MonthlyStats>({
  sqlCode: 'monthly-sales-stats',
  params: { year: 2024 }
});

if (result.execSuccess && result.execResult) {
  result.execResult.forEach(stat => {
    console.log(`${stat.customer_name}: ${stat.total_amount}元`);
  });
}

安全执行方式(推荐)

使用 sqlSafe 包装器简化错误处理:

TypeScript
import { sqlSafe } from "@lovrabet/sdk";

const { data, error } = await sqlSafe(() =>
  client.sql.execute({
    sqlCode: 'customer-orders',
    params: { customerId: '123' }
  })
);

if (error) {
  console.error('查询失败:', error.message);
  return;
}

// data 直接是查询结果数组
console.log('订单数量:', data.length);

返回值结构

TypeScript
interface SqlExecuteResult<T> {
  execSuccess: boolean;  // SQL 执行是否成功
  execResult?: T[];      // 查询结果数组(成功时)
  execError?: string;    // 错误信息(失败时)
}

TIP

使用场景

  • 复杂的多表关联查询
  • 聚合统计报表
  • 不适合用 filter 表达的复杂条件
  • 需要优化的高性能查询

INFO

SQL 管理自定义 SQL 需要在 Lovrabet 平台上预先创建和配置。你可以通过 MCP 工具或平台界面管理 SQL 查询。

API 详细说明

1. 批量查询数据(getList)

分页查询数据集中的数据,支持条件筛选、排序等功能。

SDK 用法

基础查询:

TypeScript
const response = await client.models.users.filter({
  currentPage: 1,
  pageSize: 20,
});

// 解构响应
const { paging, tableData, tableColumns } = response;

console.log("总条数:", paging.totalCount);
console.log("当前页:", paging.currentPage);
console.log("数据:", tableData);
console.log("列定义:", tableColumns);

条件查询:

TypeScript
const response = await client.models.users.filter({
  currentPage: 1,
  pageSize: 20,
  // 查询条件(根据数据集实际字段)
  status: "active",
  customer_type: "vip",
});

分页遍历:

TypeScript
async function getAllUsers() {
  const allUsers = [];
  let currentPage = 1;
  const pageSize = 50;

  while (true) {
    const { paging, tableData } = await client.models.users.filter({
      currentPage,
      pageSize,
    });

    allUsers.push(...tableData);

    // 判断是否还有更多数据
    if (currentPage * pageSize >= paging.totalCount) {
      break;
    }

    currentPage++;

    // 避免请求过快
    await new Promise((resolve) => setTimeout(resolve, 100));
  }

  return allUsers;
}

HTTP 规范

接口地址: POST /openapi/data/get-list

请求头:

Plain
X-Time-Stamp: {timestamp}
X-App-Code: {appCode}
X-Dataset-Code: {datasetCode}
X-Token: {token}

请求体:

JSON
{
  "appCode": "app-c2dd52a2",
  "datasetCode": "0fefba76fe29440194841f4825df53ff",
  "paramMap": {
    "pageSize": 10,
    "currentPage": 1,
    "status": "active",
    "customer_type": "vip",
    "create_time_start": "2024-01-01",
    "create_time_end": "2024-12-31"
  }
}

带排序的请求体示例:

JSON
{
  "appCode": "app-c2dd52a2",
  "datasetCode": "0fefba76fe29440194841f4825df53ff",
  "paramMap": {
    "pageSize": 10,
    "currentPage": 1,
    "ytSortList": [{ "gmt_create": "desc" }, { "id": "asc" }],
    "status": "active"
  }
}

响应结构说明:

data 字段下包含三个固定字段:

  • paging - 分页信息(固定字段)
  • tableData - 数据列表(固定字段)
  • tableColumns - 表格列定义(固定字段)

响应示例:

JSON
{
  "success": true,
  "msg": "查询成功",
  "data": {
    "paging": {
      "pageSize": 10,
      "totalCount": 156,
      "currentPage": 1
    },
    "tableData": [
      {
        "id": "123",
        "customer_name": "示例客户",
        "customer_type": "vip",
        "contact_person": "张三",
        "phone": "13800138000",
        "email": "example@example.com",
        "address": "北京市朝阳区",
        "status": "active",
        "credit_level": "A",
        "gmt_create": "2024-01-15 10:30:00",
        "gmt_modified": "2024-03-20 14:25:00"
      }
    ],
    "tableColumns": [
      {
        "title": "客户名称",
        "dataIndex": "customer_name"
      },
      {
        "title": "客户类型",
        "dataIndex": "customer_type"
      },
      {
        "title": "联系人",
        "dataIndex": "contact_person"
      }
    ]
  }
}

查询参数详解

分页参数:

参数类型必须默认值说明
pageSizenumber10每页记录数,最大 100
currentPagenumber1当前页码,从 1 开始

排序参数:

参数类型必须说明
ytSortListArray排序配置数组,格式: [{ "字段名": "asc/desc" }]

TIP

排序使用方式使用 SDK 时通过 getList() 的第二个参数传入 sortList,SDK 会自动转换为 ytSortList 字段。详见上方"排序功能"章节的说明。

条件查询:

条件查询参数根据不同数据集的字段而定,常见的查询方式:

TypeScript
{
  // 精确匹配
  field_name: "value",

  // 模糊查询(部分字段支持)
  field_name_like: "value",

  // 范围查询
  field_name_start: "value1",
  field_name_end: "value2",

  // IN 查询(部分字段支持)
  field_name_in: ["value1", "value2"],

  // NULL 判断(部分字段支持)
  field_name_is_null: true,
}

2. 查询单条数据(getOne)

根据唯一标识查询单条详细数据。

SDK 用法

TypeScript
// 查询单条数据
const user = await client.models.users.getOne("user-id");

console.log(user);
// 返回单个对象,包含该记录的所有字段

// 或者使用对象参数
const user = await client.models.users.getOne({
  id: 14,
});

HTTP 规范

接口地址: POST /openapi/data/get-one

请求头:

Plain
X-Time-Stamp: {timestamp}
X-App-Code: {appCode}
X-Dataset-Code: {datasetCode}
X-Token: {token}

请求体:

JSON
{
  "appCode": "app-c2dd52a2",
  "datasetCode": "0fefba76fe29440194841f4825df53ff",
  "paramMap": {
    "id": 14
  }
}

响应示例:

JSON
{
  "success": true,
  "msg": "查询成功",
  "data": {
    "id": 14,
    "customer_name": "示例客户",
    "customer_type": "vip",
    "contact_person": "张三",
    "phone": "13800138000",
    "email": "example@example.com",
    "address": "北京市朝阳区XX路XX号",
    "status": "active",
    "credit_level": "A",
    "credit_amount": 100000.0,
    "used_amount": 35000.0,
    "available_amount": 65000.0,
    "contract_start": "2024-01-01",
    "contract_end": "2024-12-31",
    "sales_person": "王经理",
    "department": "华北销售部",
    "gmt_create": "2024-01-15 10:30:00",
    "gmt_modified": "2024-03-20 14:25:00",
    "remark": "重要VIP客户,需重点维护"
  }
}

3. 新增单条数据(create)

创建一条新的数据记录。

SDK 用法

TypeScript
// 新增客户信息
const newCustomer = await client.models.users.create({
  customer_name: "新客户公司",
  customer_type: "enterprise",
  contact_person: "李经理",
  phone: "13900139000",
  email: "contact@newcustomer.com",
  address: "上海市浦东新区",
  status: "active",
  credit_level: "B",
});

console.log("新客户 ID:", newCustomer.id);
console.log("创建时间:", newCustomer.gmt_create);

HTTP 规范

接口地址: POST /openapi/data/create

请求头:

Plain
X-Time-Stamp: {timestamp}
X-App-Code: {appCode}
X-Dataset-Code: {datasetCode}
X-Token: {token}

请求体:

JSON
{
  "appCode": "app-c2dd52a2",
  "datasetCode": "0fefba76fe29440194841f4825df53ff",
  "paramMap": {
    "customer_name": "新客户公司",
    "customer_type": "enterprise",
    "contact_person": "李经理",
    "phone": "13900139000",
    "email": "contact@newcustomer.com",
    "address": "上海市浦东新区",
    "status": "active",
    "credit_level": "B"
  }
}

响应示例:

JSON
{
  "success": true,
  "msg": "创建成功",
  "data": {
    "id": 158,
    "customer_name": "新客户公司",
    "customer_type": "enterprise",
    "contact_person": "李经理",
    "phone": "13900139000",
    "email": "contact@newcustomer.com",
    "address": "上海市浦东新区",
    "status": "active",
    "credit_level": "B",
    "credit_amount": 0.0,
    "used_amount": 0.0,
    "available_amount": 0.0,
    "gmt_create": "2025-10-10 15:30:00",
    "gmt_modified": "2025-10-10 15:30:00"
  }
}

4. 更新单条数据(update)

根据 ID 更新已有数据记录的部分或全部字段。

SDK 用法

TypeScript
// 更新客户信息
const updatedCustomer = await client.models.users.update(158, {
  customer_type: "vip",
  credit_level: "A",
  credit_amount: 200000.0,
  remark: "升级为 VIP 客户,提升信用额度",
});

console.log("更新后的客户类型:", updatedCustomer.customer_type);
console.log("更新时间:", updatedCustomer.gmt_modified);

批量更新示例:

TypeScript
// 批量更新多个客户的状态
const customerIds = [101, 102, 103];

const updateResults = await Promise.all(
  customerIds.map((id) =>
    client.models.users.update(id, {
      status: "inactive",
      remark: "批量停用",
    })
  )
);

console.log(`成功更新 ${updateResults.length} 个客户`);

HTTP 规范

接口地址: POST /openapi/data/update

请求头:

Plain
X-Time-Stamp: {timestamp}
X-App-Code: {appCode}
X-Dataset-Code: {datasetCode}
X-Token: {token}

请求体:

JSON
{
  "appCode": "app-c2dd52a2",
  "datasetCode": "0fefba76fe29440194841f4825df53ff",
  "paramMap": {
    "id": 158,
    "customer_type": "vip",
    "credit_level": "A",
    "credit_amount": 200000.0,
    "remark": "升级为 VIP 客户,提升信用额度"
  }
}

响应示例:

JSON
{
  "success": true,
  "msg": "更新成功",
  "data": {
    "id": 158,
    "customer_name": "新客户公司",
    "customer_type": "vip",
    "contact_person": "李经理",
    "phone": "13900139000",
    "email": "contact@newcustomer.com",
    "address": "上海市浦东新区",
    "status": "active",
    "credit_level": "A",
    "credit_amount": 200000.0,
    "used_amount": 0.0,
    "available_amount": 200000.0,
    "gmt_create": "2025-10-10 15:30:00",
    "gmt_modified": "2025-10-10 16:45:00",
    "remark": "升级为 VIP 客户,提升信用额度"
  }
}

软删除建议

OpenAPI 目前不提供物理删除接口。如需删除数据,建议使用"软删除"方式,即通过 update() 方法更新状态字段:

TypeScript
// 推荐:使用软删除(更新状态为 deleted)
await client.models.users.update(158, {
  status: "deleted",
  deleted_at: new Date().toISOString(),
  remark: "客户要求删除数据",
});

console.log("客户已标记为删除");

软删除的优势:

  • ✅ 数据可恢复
  • ✅ 保留操作记录
  • ✅ 符合数据合规要求

错误处理

错误码说明

当请求失败时,success 字段为 false,并返回相应的错误码和错误信息。

错误码说明解决方案
1001参数错误检查请求参数是否完整、格式是否正确
1002签名验证失败检查 Access Key、签名算法、时间戳
1003时间戳过期Token 已过期(10 分钟),重新生成
1004应用不存在检查 App Code 是否正确
1005数据集不存在检查 Dataset Code 是否正确
1006无访问权限确认应用是否有该数据集的访问权限
2001查询超时优化查询条件,减少数据量
2002数据不存在检查查询条件或 ID 是否正确
3001服务器内部错误联系技术支持
4001请求频率超限降低请求频率,实施限流策略

错误响应示例

JSON
{
  "success": false,
  "msg": null,
  "data": null,
  "errorCode": 1002,
  "errorMsg": "签名验证失败,请检查 Token 生成算法"
}

SDK 错误处理

TypeScript
import { LovrabetError } from "@lovrabet/sdk";

try {
  const users = await client.models.users.filter();
} catch (error) {
  if (error instanceof LovrabetError) {
    console.error("错误码:", error.statusCode);
    console.error("错误信息:", error.message);
    console.error("错误详情:", error.details);

    // 根据错误码处理
    switch (error.statusCode) {
      case 1002:
        console.error("签名验证失败,请检查 Access Key");
        break;
      case 1003:
        console.error("Token 已过期,需要刷新");
        break;
      case 1006:
        console.error("无权访问该数据集");
        break;
      default:
        console.error("其他错误");
    }
  } else {
    console.error("未知错误:", error);
  }
}

高级用法

1. TypeScript 类型支持

TypeScript
import { createClient, ListResponse } from "@lovrabet/sdk";

// 定义数据类型
interface User {
  id: string;
  name: string;
  email: string;
  status: "active" | "inactive";
  gmt_create: string;
}

const client = createClient({
  // ... 配置
});

// 类型化查询
const response: ListResponse<User> = await client.models.users.filter();

response.tableData.forEach((user: User) => {
  console.log(user.name, user.email);
});

2. 多模型配置

TypeScript
const client = createClient({
  appCode: "your-app-code",
  accessKey: process.env.LOVRABET_ACCESS_KEY,
  models: {
    users: {
      tableName: "users",
      datasetCode: "dataset-001",
    },
    orders: {
      tableName: "orders",
      datasetCode: "dataset-002",
    },
    products: {
      tableName: "products",
      datasetCode: "dataset-003",
    },
  },
});

// 使用不同的模型
const users = await client.models.users.filter();
const orders = await client.models.orders.filter();
const products = await client.models.products.filter();

3. 响应数据转换

TypeScript
const response = await client.models.users.filter();

// 提取纯数据数组
const users = response.tableData;

// 提取列定义(用于动态构建表格 UI)
const columns = response.tableColumns.map((col) => ({
  title: col.title,
  field: col.dataIndex,
}));

// 分页信息
const { totalCount, currentPage, pageSize } = response.paging;
const totalPages = Math.ceil(totalCount / pageSize);

4. 请求拦截和日志

TypeScript
import { createClient } from "@lovrabet/sdk";

const client = createClient({
  appCode: "your-app-code",
  accessKey: process.env.LOVRABET_ACCESS_KEY,
  models: {
    /* ... */
  },
});

// 包装请求方法添加日志
const originalGetList = client.models.users.getList.bind(client.models.users);

client.models.users.getList = async function (params) {
  console.log("请求参数:", params);
  const startTime = Date.now();

  try {
    const result = await originalGetList(params);
    console.log("请求成功,耗时:", Date.now() - startTime, "ms");
    return result;
  } catch (error) {
    console.error("请求失败:", error);
    throw error;
  }
};

性能优化

1. 分页查询建议

TypeScript
// ✅ 推荐:合理的分页大小
const response = await client.models.users.filter({
  pageSize: 20, // 10-50 条较合适
});

// ❌ 避免:单次查询过多数据
const response = await client.models.users.filter({
  pageSize: 1000, // 不推荐,影响性能
});

2. 避免 N+1 查询

TypeScript
// ❌ 不推荐:循环调用 getOne
for (const id of userIds) {
  const user = await client.models.users.getOne(id);
  // 处理 user
}

// ✅ 推荐:使用 getList 批量查询
const users = await client.models.users.filter({
  id_in: userIds, // 假设支持 IN 查询
});

3. 实现缓存

TypeScript
class CachedApiClient {
  private cache = new Map<string, { data: any; timestamp: number }>();
  private cacheTTL = 60000; // 1 分钟

  async getListCached(params: any) {
    const cacheKey = JSON.stringify(params);
    const cached = this.cache.get(cacheKey);

    if (cached && Date.now() - cached.timestamp < this.cacheTTL) {
      return cached.data;
    }

    const data = await client.models.users.filter(params);
    this.cache.set(cacheKey, { data, timestamp: Date.now() });

    return data;
  }
}

4. 并发控制

TypeScript
// 限制并发数
async function batchQuery(ids: string[], concurrency = 3) {
  const results = [];

  for (let i = 0; i < ids.length; i += concurrency) {
    const batch = ids.slice(i, i + concurrency);
    const batchResults = await Promise.all(
      batch.map((id) => client.models.users.getOne(id))
    );
    results.push(...batchResults);
  }

  return results;
}

请求限制

频率限制

限制类型限制值
每分钟600 次请求
每小时10,000 次请求
每天100,000 次请求

数据量限制

限制类型限制值
单次查询最多返回100 条记录
响应体最大10MB
请求体最大1MB

并发限制

限制类型限制值
每个应用最多并发连接10 个

TIP

性能建议

  • 使用连接池管理请求
  • 实现请求队列和限流机制
  • 合理设置超时时间

原始 HTTP 请求(高级)

INFO

仅供参考推荐使用 SDK,以下内容仅供需要底层实现的开发者参考。

签名生成

TypeScript
import crypto from "crypto";

function generateToken(
  timestamp: number,
  appCode: string,
  datasetCode: string,
  accessKey: string,
  secretKey: string = "lovrabet"
): string {
  const params: Record<string, string> = {
    accessKey: accessKey,
    timeStamp: timestamp.toString(),
    appCode: appCode,
  };

  if (datasetCode) {
    params.datasetCode = datasetCode;
  }

  // 按字典序排序参数
  const sortedParams = Object.keys(params)
    .sort()
    .map((key) => `${key}=${params[key]}`)
    .join("&");

  // 计算 HMAC-SHA256
  return crypto
    .createHmac("sha256", secretKey)
    .update(sortedParams, "utf8")
    .digest("base64");
}

HTTP 请求示例

TypeScript
async function getListRaw() {
  const timestamp = Date.now();
  const appCode = "app-c2dd52a2";
  const datasetCode = "0fefba76fe29440194841f4825df53ff";
  const accessKey = "your-access-key";

  const token = generateToken(timestamp, appCode, datasetCode, accessKey);

  const response = await fetch(
    "https://runtime.lovrabet.com/openapi/data/get-list",
    {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "X-Time-Stamp": timestamp.toString(),
        "X-App-Code": appCode,
        "X-Dataset-Code": datasetCode,
        "X-Token": token,
      },
      body: JSON.stringify({
        appCode: appCode,
        datasetCode: datasetCode,
        paramMap: {
          pageSize: 10,
          currentPage: 1,
        },
      }),
    }
  );

  return await response.json();
}

最佳实践

1. 错误处理和重试

TypeScript
async function apiCallWithRetry(
  fn: () => Promise<any>,
  maxRetries = 3,
  delay = 1000
) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await fn();
    } catch (error) {
      if (error instanceof LovrabetError) {
        // Token 过期可以重试
        if (error.statusCode === 1003 && i < maxRetries - 1) {
          await new Promise((resolve) => setTimeout(resolve, delay));
          continue;
        }
      }
      throw error;
    }
  }
}

// 使用
const users = await apiCallWithRetry(() => client.models.users.filter());

2. 日志记录

TypeScript
function logApiCall(
  method: string,
  params: any,
  result: any,
  duration: number
) {
  console.log({
    timestamp: new Date().toISOString(),
    method: method,
    params: params,
    success: true,
    duration: duration,
    recordCount: result.tableData?.length || 0,
  });
}

3. 监控和告警

TypeScript
class ApiMonitor {
  private errorCount = 0;
  private errorThreshold = 10;

  async callWithMonitoring(fn: () => Promise<any>) {
    try {
      const result = await fn();
      this.errorCount = 0; // 重置错误计数
      return result;
    } catch (error) {
      this.errorCount++;

      if (this.errorCount >= this.errorThreshold) {
        // 触发告警
        this.sendAlert("API 错误率过高");
      }

      throw error;
    }
  }

  private sendAlert(message: string) {
    // 发送告警通知
    console.error("告警:", message);
  }
}

相关文档

需要帮助?

如遇到问题:

  1. 查看本文档的错误码说明
  2. 查看 GitHub Issues
  3. 联系商务经理获取技术支持

基于飞书知识库同步生成,内容以飞书源文档为准