API Reference
This document provides a complete reference for all Lovrabet OpenAPI interfaces, including SDK usage and underlying HTTP specifications.
Basic Information
Environment URLs
| Environment | Domain |
|---|---|
| Production | https://runtime.lovrabet.com |
Request Specifications
- Request Method: All interfaces use
POST - Content Type:
application/json - Character Encoding:
UTF-8 - Timeout Setting: 30 seconds recommended
Authentication Method
All requests require the following authentication information in HTTP Headers:
| Header Name | Description | Example |
|---|---|---|
| X-Time-Stamp | Timestamp (milliseconds) | 1758903130713 |
| X-App-Code | Application code | app-c2dd52a2 |
| X-Dataset-Code | Dataset code (required for some APIs) | 0fefba76fe29...ff |
| X-Token | Signature Token | jdqqGtzecF2I6FIW... |
The SDK automatically adds all required headers without manual intervention.
OpenAPI Interface List
Complete Interface List
Below are all interfaces provided by Lovrabet OpenAPI with detailed information:
| Interface Name | HTTP Method | Full URL Path | SDK Method | Description |
|---|---|---|---|---|
| Batch query data | POST | /openapi/data/get-list | getList(params?, sortList?) | Paginated query with filtering and sorting |
| Query single data | POST | /openapi/data/get-one | getOne(id) | Get single data detail by ID |
| Create data | POST | /openapi/data/create | create(data) | Create new data record |
| Update data | POST | /openapi/data/update | update(id, data) | Update existing data record |
OpenAPI currently does not support delete(), getSelectOptions(), and excelExport() operations. For these features, please use Cookie-based WebAPI mode.
Request Parameter Specifications
All OpenAPI request bodies follow this structure:
{
appCode: string; // Application code (required for all interfaces)
datasetCode: string; // Dataset code (required for all data operations)
paramMap: { // Business parameter object
// Specific parameters vary by interface
}
}
Authentication Information Delivery:
- OpenAPI authentication information is not in the request body, but passed through HTTP Headers:
X-Time-Stamp: TimestampX-App-Code: Application codeX-Dataset-Code: Dataset codeX-Token: Signature Token
- SDK automatically handles these headers, developers don't need to add them manually
Interface Parameter Details
1. Batch Query Data (getList)
URL: POST /openapi/data/get-list
Request Body Parameters:
{
appCode: string;
datasetCode: string;
paramMap: {
currentPage?: number; // Current page number, starts from 1
pageSize?: number; // Records per page
ytSortList?: SortList; // Sort configuration (auto-added via SDK sortList parameter)
[key: string]: any; // Other query conditions (based on dataset fields)
}
}
Parameter Description:
| Parameter Name | Type | Required | Default | Description |
|---|---|---|---|---|
appCode | string | ✅ Yes | - | Application code |
datasetCode | string | ✅ Yes | - | Dataset code |
paramMap.currentPage | number | ❌ No | 1 | Current page number, starts from 1 |
paramMap.pageSize | number | ❌ No | 20 | Records per page, max 100 |
paramMap.ytSortList | SortList | ❌ No | - | Sort configuration array, auto-generated from SDK sortList |
paramMap.[fieldName] | any | ❌ No | - | Other query conditions based on dataset field definitions |
Query Condition Examples:
Based on different dataset fields, you can use the following query patterns:
{
// Exact match
status: "active",
customer_type: "vip",
// Fuzzy search (field name with _like suffix)
name_like: "Zhang",
// Range query (field name with _start/_end suffix)
create_time_start: "2024-01-01",
create_time_end: "2024-12-31",
amount_start: 1000,
amount_end: 5000,
// IN query (field name with _in suffix, value as array)
status_in: ["active", "pending"],
// IS NULL query (field name with _is_null suffix)
deleted_at_is_null: true,
}
Sorting Feature (ytSortList):
OpenAPI uses the ytSortList field for sorting, passed through SDK's sortList parameter:
import { SortOrder } from "@lovrabet/sdk";
// SDK usage (recommended)
const result = await client.models.users.filter(
{ currentPage: 1, pageSize: 20 },
[
{ priority: SortOrder.DESC }, // Priority descending
{ createTime: SortOrder.DESC }, // Create time descending
{ name: SortOrder.ASC }, // Name ascending
]
);
// SDK automatically converts sortList to ytSortList field in paramMap
// Actual request body: { appCode, datasetCode, paramMap: { ytSortList: [...] } }
- OpenAPI only supports sorting through
ytSortListfield - When using SDK, pass sort configuration through the second parameter
sortListofgetList() - SDK automatically converts
sortListtoytSortListformat
Response Data (data field):
{
paging: {
pageSize: number; // Records per page
totalCount: number; // Total record count
currentPage: number; // Current page number
}
tableData: Array<T>; // Data list array
tableColumns: Array<{
title: string; // Column title
dataIndex: string; // Field name
}>;
}
2. Query Single Data (getOne)
URL: POST /openapi/data/get-one
Request Body Parameters:
{
appCode: string;
datasetCode: string;
paramMap: {
id: string | number; // Record ID
}
}
Parameter Description:
| Parameter Name | Type | Required | Description |
|---|---|---|---|
appCode | string | ✅ Yes | Application code |
datasetCode | string | ✅ Yes | Dataset code |
paramMap.id | string/number | ✅ Yes | Record ID to query |
Response Data (data field):
{
id: string | number; // Record ID
[key: string]: any; // Other fields based on dataset definition
}
3. Create Data (create)
URL: POST /openapi/data/create
Request Body Parameters:
{
appCode: string;
datasetCode: string;
paramMap: {
[key: string]: any; // Data fields to create
}
}
Parameter Description:
| Parameter Name | Type | Required | Description |
|---|---|---|---|
appCode | string | ✅ Yes | Application code |
datasetCode | string | ✅ Yes | Dataset code |
paramMap.[fieldName] | any | Based on field definition | Data to create, fields and requirements based on dataset definition |
Notes:
- System fields (such as
id,gmt_create,gmt_modified) are auto-generated, no need to provide - Required fields must be provided, otherwise parameter error will be returned
- Field types must match dataset definition
Response Data (data field):
{
id: string | number; // ID of newly created record
[key: string]: any; // Complete record data (including auto-generated fields)
}
4. Update Data (update)
URL: POST /openapi/data/update
Request Body Parameters:
{
appCode: string;
datasetCode: string;
paramMap: {
id: string | number; // Record ID to update
[key: string]: any; // Fields to update
}
}
Parameter Description:
| Parameter Name | Type | Required | Description |
|---|---|---|---|
appCode | string | ✅ Yes | Application code |
datasetCode | string | ✅ Yes | Dataset code |
paramMap.id | string/number | ✅ Yes | Record ID to update |
paramMap.[fieldName] | any | ❌ No | Fields to update, only need to provide fields to modify (partial update) |
Notes:
- Supports partial updates, only need to provide fields to modify
gmt_modifiedfield is automatically updated- Cannot modify
idandgmt_createfields
Response Data (data field):
{
id: string | number; // Record ID
[key: string]: any; // Complete updated record data
}
Response Structure
Common Response Format
All interface responses contain the following top-level fields (returned by platform gateway):
{
success: boolean; // Whether request succeeded
msg: string; // Response message
data: any; // Response data
errorCode?: number; // Error code (returned on failure)
errorMsg?: string; // Error message (returned on failure)
}
getList Response Fixed Fields
The data field of getList interface contains the following three fixed fields (SDK return structure is consistent with platform):
{
paging: {
// 【Fixed field】Pagination information
pageSize: number; // Records per page
totalCount: number; // Total record count
currentPage: number; // Current page number
}
tableData: Array<T>; // 【Fixed field】Data list array
tableColumns: Array<{
// 【Fixed field】Table column definition
title: string; // Column title
dataIndex: string; // Field name
}>;
}
SDK Usage
Create Client
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 Method List
Each model instance provides the following methods:
| Method | Description | Corresponding API |
|---|---|---|
getList(params?) | Batch query data | /openapi/data/get-list |
getOne(id) | Query single data | /openapi/data/get-one |
create(data) | Create single data | /openapi/data/create |
update(id, data) | Update single data | /openapi/data/update |
Detailed API Description
1. Batch Query Data (getList)
Paginated query of data in dataset, supports filtering, sorting, etc.
SDK Usage
Basic Query:
const response = await client.models.users.filter({
currentPage: 1,
pageSize: 20,
});
// Destructure response
const { paging, tableData, tableColumns } = response;
console.log("Total count:", paging.totalCount);
console.log("Current page:", paging.currentPage);
console.log("Data:", tableData);
console.log("Column definitions:", tableColumns);
Conditional Query:
const response = await client.models.users.filter({
currentPage: 1,
pageSize: 20,
// Query conditions (based on actual dataset fields)
status: "active",
customer_type: "vip",
});
Paginated Iteration:
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);
// Check if there's more data
if (currentPage * pageSize >= paging.totalCount) {
break;
}
currentPage++;
// Avoid request flooding
await new Promise((resolve) => setTimeout(resolve, 100));
}
return allUsers;
}
HTTP Specifications
Interface URL: POST /openapi/data/get-list
Request Headers:
X-Time-Stamp: {timestamp}
X-App-Code: {appCode}
X-Dataset-Code: {datasetCode}
X-Token: {token}
Request Body:
{
"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"
}
}
Request Body with Sorting Example:
{
"appCode": "app-c2dd52a2",
"datasetCode": "0fefba76fe29440194841f4825df53ff",
"paramMap": {
"pageSize": 10,
"currentPage": 1,
"ytSortList": [{ "gmt_create": "desc" }, { "id": "asc" }],
"status": "active"
}
}
Response Structure Description:
The data field contains three fixed fields:
paging- Pagination information (fixed field)tableData- Data list (fixed field)tableColumns- Table column definition (fixed field)
Response Example:
{
"success": true,
"msg": "Query successful",
"data": {
"paging": {
"pageSize": 10,
"totalCount": 156,
"currentPage": 1
},
"tableData": [
{
"id": "123",
"customer_name": "Example Customer",
"customer_type": "vip",
"contact_person": "Zhang San",
"phone": "13800138000",
"email": "example@example.com",
"address": "Chaoyang District, Beijing",
"status": "active",
"credit_level": "A",
"gmt_create": "2024-01-15 10:30:00",
"gmt_modified": "2024-03-20 14:25:00"
}
],
"tableColumns": [
{
"title": "Customer Name",
"dataIndex": "customer_name"
},
{
"title": "Customer Type",
"dataIndex": "customer_type"
},
{
"title": "Contact Person",
"dataIndex": "contact_person"
}
]
}
}
Query Parameter Details
Pagination Parameters:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
pageSize | number | No | 10 | Records per page, max 100 |
currentPage | number | No | 1 | Current page, starts from 1 |
Sorting Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
ytSortList | Array | No | Sort configuration array, format: [{ "fieldName": "asc/desc" }] |
When using SDK, pass sort configuration through the second parameter sortList of getList(), SDK automatically converts to ytSortList field.
See "Sorting Feature" section above for details.
Conditional Query:
Query parameters vary by dataset fields, common query methods:
{
// Exact match
field_name: "value",
// Fuzzy search (some fields support)
field_name_like: "value",
// Range query
field_name_start: "value1",
field_name_end: "value2",
// IN query (some fields support)
field_name_in: ["value1", "value2"],
// NULL check (some fields support)
field_name_is_null: true,
}
2. Query Single Data (getOne)
Query single detailed data by unique identifier.
SDK Usage
// Query single data
const user = await client.models.users.getOne("user-id");
console.log(user);
// Returns single object containing all fields of the record
// Or use object parameter
const user = await client.models.users.getOne({
id: 14,
});
HTTP Specifications
Interface URL: POST /openapi/data/get-one
Request Headers:
X-Time-Stamp: {timestamp}
X-App-Code: {appCode}
X-Dataset-Code: {datasetCode}
X-Token: {token}
Request Body:
{
"appCode": "app-c2dd52a2",
"datasetCode": "0fefba76fe29440194841f4825df53ff",
"paramMap": {
"id": 14
}
}
Response Example:
{
"success": true,
"msg": "Query successful",
"data": {
"id": 14,
"customer_name": "Example Customer",
"customer_type": "vip",
"contact_person": "Zhang San",
"phone": "13800138000",
"email": "example@example.com",
"address": "XX Road XX, Chaoyang District, Beijing",
"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": "Manager Wang",
"department": "North China Sales Department",
"gmt_create": "2024-01-15 10:30:00",
"gmt_modified": "2024-03-20 14:25:00",
"remark": "Important VIP customer, requires priority maintenance"
}
}
3. Create Single Data (create)
Create a new data record.
SDK Usage
// Create customer information
const newCustomer = await client.models.users.create({
customer_name: "New Customer Company",
customer_type: "enterprise",
contact_person: "Manager Li",
phone: "13900139000",
email: "contact@newcustomer.com",
address: "Pudong New Area, Shanghai",
status: "active",
credit_level: "B",
});
console.log("New customer ID:", newCustomer.id);
console.log("Created time:", newCustomer.gmt_create);
HTTP Specifications
Interface URL: POST /openapi/data/create
Request Headers:
X-Time-Stamp: {timestamp}
X-App-Code: {appCode}
X-Dataset-Code: {datasetCode}
X-Token: {token}
Request Body:
{
"appCode": "app-c2dd52a2",
"datasetCode": "0fefba76fe29440194841f4825df53ff",
"paramMap": {
"customer_name": "New Customer Company",
"customer_type": "enterprise",
"contact_person": "Manager Li",
"phone": "13900139000",
"email": "contact@newcustomer.com",
"address": "Pudong New Area, Shanghai",
"status": "active",
"credit_level": "B"
}
}
Response Example:
{
"success": true,
"msg": "Created successfully",
"data": {
"id": 158,
"customer_name": "New Customer Company",
"customer_type": "enterprise",
"contact_person": "Manager Li",
"phone": "13900139000",
"email": "contact@newcustomer.com",
"address": "Pudong New Area, Shanghai",
"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 Single Data (update)
Update partial or all fields of an existing data record by ID.
SDK Usage
// Update customer information
const updatedCustomer = await client.models.users.update(158, {
customer_type: "vip",
credit_level: "A",
credit_amount: 200000.0,
remark: "Upgraded to VIP customer, increased credit limit",
});
console.log("Updated customer type:", updatedCustomer.customer_type);
console.log("Update time:", updatedCustomer.gmt_modified);
Batch Update Example:
// Batch update multiple customer statuses
const customerIds = [101, 102, 103];
const updateResults = await Promise.all(
customerIds.map((id) =>
client.models.users.update(id, {
status: "inactive",
remark: "Batch deactivation",
})
)
);
console.log(`Successfully updated ${updateResults.length} customers`);
HTTP Specifications
Interface URL: POST /openapi/data/update
Request Headers:
X-Time-Stamp: {timestamp}
X-App-Code: {appCode}
X-Dataset-Code: {datasetCode}
X-Token: {token}
Request Body:
{
"appCode": "app-c2dd52a2",
"datasetCode": "0fefba76fe29440194841f4825df53ff",
"paramMap": {
"id": 158,
"customer_type": "vip",
"credit_level": "A",
"credit_amount": 200000.0,
"remark": "Upgraded to VIP customer, increased credit limit"
}
}
Response Example:
{
"success": true,
"msg": "Updated successfully",
"data": {
"id": 158,
"customer_name": "New Customer Company",
"customer_type": "vip",
"contact_person": "Manager Li",
"phone": "13900139000",
"email": "contact@newcustomer.com",
"address": "Pudong New Area, Shanghai",
"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": "Upgraded to VIP customer, increased credit limit"
}
}
OpenAPI currently does not provide physical deletion interface. If you need to delete data, it's recommended to use "soft delete" approach by updating a status field via update() method:
// Recommended: Use soft delete (update status to deleted)
await client.models.users.update(158, {
status: "deleted",
deleted_at: new Date().toISOString(),
remark: "Deleted per customer request",
});
console.log("Customer marked as deleted");
Advantages of soft delete:
- ✅ Data is recoverable
- ✅ Maintains operation records
- ✅ Complies with data compliance requirements
Error Handling
Error Code Description
When a request fails, the success field is false, and corresponding error code and message are returned.
| Error Code | Description | Solution |
|---|---|---|
| 1001 | Parameter error | Check if request parameters are complete and formatted correctly |
| 1002 | Signature verification failed | Check Access Key, signature algorithm, timestamp |
| 1003 | Timestamp expired | Token expired (10 minutes), regenerate |
| 1004 | Application not found | Check if App Code is correct |
| 1005 | Dataset not found | Check if Dataset Code is correct |
| 1006 | No access permission | Confirm if application has access to dataset |
| 2001 | Query timeout | Optimize query conditions, reduce data volume |
| 2002 | Data not found | Check if query conditions or ID is correct |
| 3001 | Internal server error | Contact technical support |
| 4001 | Request rate exceeded | Reduce request frequency, implement rate limiting |
Error Response Example
{
"success": false,
"msg": null,
"data": null,
"errorCode": 1002,
"errorMsg": "Signature verification failed, please check Token generation algorithm"
}
SDK Error Handling
import { LovrabetError } from "@lovrabet/sdk";
try {
const users = await client.models.users.filter();
} catch (error) {
if (error instanceof LovrabetError) {
console.error("Error code:", error.statusCode);
console.error("Error message:", error.message);
console.error("Error details:", error.details);
// Handle based on error code
switch (error.statusCode) {
case 1002:
console.error("Signature verification failed, check Access Key");
break;
case 1003:
console.error("Token expired, need to refresh");
break;
case 1006:
console.error("No permission to access this dataset");
break;
default:
console.error("Other error");
}
} else {
console.error("Unknown error:", error);
}
}
Advanced Usage
1. TypeScript Type Support
import { createClient, ListResponse } from "@lovrabet/sdk";
// Define data type
interface User {
id: string;
name: string;
email: string;
status: "active" | "inactive";
gmt_create: string;
}
const client = createClient({
// ... configuration
});
// Typed query
const response: ListResponse<User> = await client.models.users.filter();
response.tableData.forEach((user: User) => {
console.log(user.name, user.email);
});
2. Multi-Model Configuration
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",
},
},
});
// Use different models
const users = await client.models.users.filter();
const orders = await client.models.orders.filter();
const products = await client.models.products.filter();
3. Response Data Transformation
const response = await client.models.users.filter();
// Extract pure data array
const users = response.tableData;
// Extract column definitions (for dynamic table UI construction)
const columns = response.tableColumns.map((col) => ({
title: col.title,
field: col.dataIndex,
}));
// Pagination information
const { totalCount, currentPage, pageSize } = response.paging;
const totalPages = Math.ceil(totalCount / pageSize);
4. Request Interception and Logging
import { createClient } from "@lovrabet/sdk";
const client = createClient({
appCode: "your-app-code",
accessKey: process.env.LOVRABET_ACCESS_KEY,
models: {
/* ... */
},
});
// Wrap request method to add logging
const originalGetList = client.models.users.getList.bind(client.models.users);
client.models.users.getList = async function (params) {
console.log("Request parameters:", params);
const startTime = Date.now();
try {
const result = await originalGetList(params);
console.log("Request successful, time:", Date.now() - startTime, "ms");
return result;
} catch (error) {
console.error("Request failed:", error);
throw error;
}
};
Performance Optimization
1. Pagination Query Recommendations
// ✅ Recommended: Reasonable page size
const response = await client.models.users.filter({
pageSize: 20, // 10-50 records is appropriate
});
// ❌ Avoid: Querying too much data at once
const response = await client.models.users.filter({
pageSize: 1000, // Not recommended, affects performance
});
2. Avoid N+1 Queries
// ❌ Not recommended: Loop calling getOne
for (const id of userIds) {
const user = await client.models.users.getOne(id);
// Process user
}
// ✅ Recommended: Use getList for batch query
const users = await client.models.users.filter({
id_in: userIds, // Assuming IN query is supported
});
3. Implement Caching
class CachedApiClient {
private cache = new Map<string, { data: any; timestamp: number }>();
private cacheTTL = 60000; // 1 minute
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. Concurrency Control
// Limit concurrency
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;
}
Request Limits
Rate Limits
| Limit Type | Limit Value |
|---|---|
| Per minute | 600 requests |
| Per hour | 10,000 requests |
| Per day | 100,000 requests |
Data Volume Limits
| Limit Type | Limit Value |
|---|---|
| Max records per single query | 100 records |
| Max response body size | 10MB |
| Max request body size | 1MB |
Concurrency Limits
| Limit Type | Limit Value |
|---|---|
| Max concurrent connections per app | 10 |
- Use connection pools to manage requests
- Implement request queues and rate limiting mechanisms
- Set reasonable timeout values
Raw HTTP Requests (Advanced)
Using SDK is recommended. The following content is for developers who need low-level implementation.
Signature Generation
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;
}
// Sort parameters by dictionary order
const sortedParams = Object.keys(params)
.sort()
.map((key) => `${key}=${params[key]}`)
.join("&");
// Calculate HMAC-SHA256
return crypto
.createHmac("sha256", secretKey)
.update(sortedParams, "utf8")
.digest("base64");
}
HTTP Request Example
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();
}
Best Practices
1. Error Handling and Retry
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 expiration can be retried
if (error.statusCode === 1003 && i < maxRetries - 1) {
await new Promise((resolve) => setTimeout(resolve, delay));
continue;
}
}
throw error;
}
}
}
// Usage
const users = await apiCallWithRetry(() => client.models.users.filter());
2. Logging
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. Monitoring and Alerting
class ApiMonitor {
private errorCount = 0;
private errorThreshold = 10;
async callWithMonitoring(fn: () => Promise<any>) {
try {
const result = await fn();
this.errorCount = 0; // Reset error count
return result;
} catch (error) {
this.errorCount++;
if (this.errorCount >= this.errorThreshold) {
// Trigger alert
this.sendAlert("API error rate too high");
}
throw error;
}
}
private sendAlert(message: string) {
// Send alert notification
console.error("Alert:", message);
}
}
Related Documentation
- Authentication Guide - Learn about authentication mechanisms and Token management
- Quick Start - Get started quickly with examples
- Introduction - Learn about OpenAPI overview
Need Help?
If you encounter issues:
- Check error code descriptions in this document
- Check GitHub Issues
- Contact your business manager for technical support