Raw APIs and the Node.js SDK
Instant API is the data API layer every dataset gets automatically, with three calling modes: WebAPI, OpenAPI, and Client API. This page first explains how the three modes differ in use cases, authentication, and URLs; then it walks through the 9 core APIs with raw curl examples in WebAPI mode; finally, it shows how the Node.js SDK wraps them.
1. The Three Calling Modes
| Mode | Use cases | Identity semantics | Coverage |
|---|---|---|---|
| WebAPI | Lovrabet-generated web pages, micro-frontend child apps, logged-in users accessing data in the browser | The current logged-in user | All 9 core Instant APIs |
| OpenAPI | Third-party systems, server-side jobs, Agent gateways, cross-system integration | App-level access credentials | A subset of data operations; see the OpenAPI docs |
| Client API | CLIs, Agents, local scripts, and server-side tools that access data as an individual | Personal identity authentication | All 9 core Instant APIs |
How to choose:
- If you're already in a Lovrabet page or a same-domain browser environment, use WebAPI.
- For server-to-server integration from an external system, use OpenAPI.
- When an automation tool must act as a specific user, use Client API.
2. Authentication
| Mode | Authentication | Header or credential | Notes |
|---|---|---|---|
| WebAPI | Cookie session authentication | The browser sends the cookie automatically; Node.js can pass an explicit Cookie header | Inherits the current logged-in user's permissions |
| OpenAPI | HMAC-SHA256 signature | X-Time-Stamp, X-App-Code, X-Dataset-Code, X-Token | The AccessKey must stay on the server and never appear in frontend code |
| Client API | Personal identity authentication | X-User-AK | Represents a specific individual — ideal for CLIs, Agents, scripts, and server-side tools |
3. URL Format Differences
| Mode | URL format | Request body | Method naming |
|---|---|---|---|
| WebAPI | /api/{appCode}/{datasetCode}/{method} | Business parameters passed directly | camelCase, e.g. getOne, batchCreate |
| OpenAPI | /openapi/data/{method} | { appCode, datasetCode, paramMap }; batchCreate uses paramList | Some methods use kebab-case, e.g. get-one, batch-create |
| Client API | /client/{appCode}/{datasetCode}/{method} | Business parameters passed directly | camelCase, e.g. getOne, batchCreate |
4. Conventions Used on This Page
The curl examples on this page use the raw WebAPI. WebAPI supports all 9 Instant APIs with a fixed path rule:
POST {runtimeDomain}/api/{appCode}/{datasetCode}/{method}WebAPI authenticates with a cookie. The request body carries business parameters directly — no appCode, datasetCode, or paramMap wrapper:
export RUNTIME_DOMAIN="https://runtime.lovrabet.com"
export APP_CODE="app_xxx"
export DATASET_CODE="dataset_xxx"
export LOVRABET_COOKIE="your-session-cookie"curl -X POST "$RUNTIME_DOMAIN/api/$APP_CODE/$DATASET_CODE/filter" \
-H "Content-Type: application/json" \
-H "Cookie: $LOVRABET_COOKIE" \
-d '{"currentPage":1,"pageSize":20}'If your runtime uses Client API with personal authentication, switch the path to /client/{appCode}/{datasetCode}/{method}. The request body still carries business parameters directly, and authentication uses the X-User-AK header:
curl -X POST "$RUNTIME_DOMAIN/client/$APP_CODE/$DATASET_CODE/filter" \
-H "Content-Type: application/json" \
-H "X-User-AK: $LOVRABET_USER_AK" \
-d '{"currentPage":1,"pageSize":20}'OpenAPI differs from WebAPI in URL, authentication, and request body. Don't infer OpenAPI details from the curl examples here — see OpenAPI.
5. Detailed SDK Documentation
This page only maps Node.js SDK methods to the raw APIs — it doesn't cover full SDK installation, configuration, authentication, error handling, or the type system. For details, see:
| Document | Purpose |
|---|---|
| TypeScript SDK | Full Node.js / TypeScript SDK integration, model configuration, authentication, and method reference |
| Java SDK | Java server-side integration, request objects, authentication, and call examples |
| OpenAPI | OpenAPI authentication, signing, paths, request bodies, and the full API reference |
6. Node.js SDK Basics
A minimal model configuration for the Node.js SDK:
import { createClient } from "@lovrabet/sdk";
const client = createClient({
appCode: process.env.LOVRABET_APP_CODE,
runtimeDomain: process.env.LOVRABET_RUNTIME_DOMAIN || "https://runtime.lovrabet.com",
cookie: process.env.LOVRABET_COOKIE,
models: [
{
tableName: "orders",
datasetCode: process.env.LOVRABET_DATASET_CODE!,
alias: "orders",
},
],
});
const orders = client.models.orders;In cookie/WebAPI mode, the SDK sends orders.filter(params) as:
POST /api/{appCode}/{datasetCode}/filter
body: paramsIn Client API mode, it sends:
POST /client/{appCode}/{datasetCode}/filter
body: params7. API Summary
| API | WebAPI / Client API path | OpenAPI path | Node.js SDK method | Description |
|---|---|---|---|---|
filter | /api/{appCode}/{datasetCode}/filter or /client/{appCode}/{datasetCode}/filter | /openapi/data/filter | client.models.<alias>.filter(params) | Lists, search, filtering, pagination |
aggregate | /api/{appCode}/{datasetCode}/aggregate or /client/{appCode}/{datasetCode}/aggregate | /openapi/data/aggregate | client.models.<alias>.aggregate(params) | Grouped statistics, sums, counts, averages |
getOne | /api/{appCode}/{datasetCode}/getOne or /client/{appCode}/{datasetCode}/getOne | /openapi/data/get-one | client.models.<alias>.getOne(id) | Read a single record by ID |
create | /api/{appCode}/{datasetCode}/create or /client/{appCode}/{datasetCode}/create | /openapi/data/create | client.models.<alias>.create(data) | Create a single record |
batchCreate | /api/{appCode}/{datasetCode}/batchCreate or /client/{appCode}/{datasetCode}/batchCreate | /openapi/data/batch-create | client.models.<alias>.batchCreate(items) | Create records in bulk |
update | /api/{appCode}/{datasetCode}/update or /client/{appCode}/{datasetCode}/update | /openapi/data/update | client.models.<alias>.update(id, data) or update({ id, ...data }) | Update one or many records |
delete | /api/{appCode}/{datasetCode}/delete or /client/{appCode}/{datasetCode}/delete | Not supported | client.models.<alias>.delete(id) or delete({ id }) | Delete one or many records |
getSelectOptions | /api/{appCode}/{datasetCode}/getSelectOptions or /client/{appCode}/{datasetCode}/getSelectOptions | Not supported | client.models.<alias>.getSelectOptions(params) | Fetch dropdown options |
excelExport | /api/{appCode}/{datasetCode}/excelExport or /client/{appCode}/{datasetCode}/excelExport | Not supported | client.models.<alias>.excelExport(params) | Export an Excel file |
The OpenAPI request body differs from WebAPI / Client API: OpenAPI puts business parameters in paramMap, and batchCreate uses paramList. For signing details and request bodies, see OpenAPI.
8. The 9 APIs in Detail
8.1 filter
filter queries a batch of records, with support for conditions, field selection, sorting, and pagination.
curl -X POST "$RUNTIME_DOMAIN/api/$APP_CODE/$DATASET_CODE/filter" \
-H "Content-Type: application/json" \
-H "Cookie: $LOVRABET_COOKIE" \
-d '{
"where": {
"$and": [
{ "status": { "$eq": "paid" } },
{ "amount": { "$gte": 100 } }
]
},
"select": ["id", "orderNo", "status", "amount", "createdAt"],
"orderBy": [{ "createdAt": "desc" }],
"currentPage": 1,
"pageSize": 20
}'SDK wrapper:
const result = await orders.filter({
where: {
$and: [
{ status: { $eq: "paid" } },
{ amount: { $gte: 100 } },
],
},
select: ["id", "orderNo", "status", "amount", "createdAt"],
orderBy: [{ createdAt: "desc" }],
currentPage: 1,
pageSize: 20,
});The response is a paginated structure whose key fields are tableData, paging, and tableColumns.
8.2 aggregate
aggregate computes aggregate statistics. It supports SUM, COUNT, and AVG, plus groupBy, having, and orderBy.
curl -X POST "$RUNTIME_DOMAIN/api/$APP_CODE/$DATASET_CODE/aggregate" \
-H "Content-Type: application/json" \
-H "Cookie: $LOVRABET_COOKIE" \
-d '{
"select": ["status"],
"aggregate": [
{ "type": "COUNT", "field": "id", "alias": "order_count" },
{ "type": "SUM", "field": "amount", "alias": "total_amount", "round": true, "precision": 2 }
],
"where": { "createdAt": { "$gte": "2026-01-01" } },
"groupBy": ["status"],
"having": [
{ "columnName": "total_amount", "condition": { "$gte": 10000 } }
],
"orderBy": [{ "total_amount": "desc" }],
"currentPage": 1,
"pageSize": 20
}'SDK wrapper:
const result = await orders.aggregate({
select: ["status"],
aggregate: [
{ type: "COUNT", field: "id", alias: "order_count" },
{ type: "SUM", field: "amount", alias: "total_amount", round: true, precision: 2 },
],
where: { createdAt: { $gte: "2026-01-01" } },
groupBy: ["status"],
having: [
{ columnName: "total_amount", condition: { $gte: 10000 } },
],
orderBy: [{ total_amount: "desc" }],
currentPage: 1,
pageSize: 20,
});The response is also a paginated structure; each item in tableData is an aggregation result.
8.3 getOne
getOne reads a single record by ID.
curl -X POST "$RUNTIME_DOMAIN/api/$APP_CODE/$DATASET_CODE/getOne" \
-H "Content-Type: application/json" \
-H "Cookie: $LOVRABET_COOKIE" \
-d '{"id":"order_001"}'SDK wrapper:
const order = await orders.getOne("order_001");
const sameOrder = await orders.getOne({ id: "order_001" });When you know the ID, call getOne directly — don't emulate a single-record fetch with filter.
8.4 create
create inserts one record; the request body is simply the business fields to write.
curl -X POST "$RUNTIME_DOMAIN/api/$APP_CODE/$DATASET_CODE/create" \
-H "Content-Type: application/json" \
-H "Cookie: $LOVRABET_COOKIE" \
-d '{
"customerId": "customer_001",
"amount": 199.9,
"status": "pending"
}'SDK wrapper:
const created = await orders.create({
customerId: "customer_001",
amount: 199.9,
status: "pending",
});Shared rules such as defaults, uniqueness, and state-machine checks belong in the Before Hook for create.
8.5 batchCreate
batchCreate inserts multiple records in one call. The raw WebAPI request body is an array — no need to wrap it as { items: [...] }.
curl -X POST "$RUNTIME_DOMAIN/api/$APP_CODE/$DATASET_CODE/batchCreate" \
-H "Content-Type: application/json" \
-H "Cookie: $LOVRABET_COOKIE" \
-d '[
{ "customerId": "customer_001", "amount": 100, "status": "pending" },
{ "customerId": "customer_002", "amount": 200, "status": "pending" }
]'SDK wrapper:
const createdRows = await orders.batchCreate([
{ customerId: "customer_001", amount: 100, status: "pending" },
{ customerId: "customer_002", amount: 200, status: "pending" },
]);The SDK validates that the input is a non-empty array with at most 1,000 items.
8.6 update
update modifies one or more records. The request body must include id; the remaining fields are the values to update.
curl -X POST "$RUNTIME_DOMAIN/api/$APP_CODE/$DATASET_CODE/update" \
-H "Content-Type: application/json" \
-H "Cookie: $LOVRABET_COOKIE" \
-d '{
"id": "order_001",
"status": "paid",
"paidAt": "2026-04-23T10:00:00Z"
}'To update in bulk, pass id as an array:
curl -X POST "$RUNTIME_DOMAIN/api/$APP_CODE/$DATASET_CODE/update" \
-H "Content-Type: application/json" \
-H "Cookie: $LOVRABET_COOKIE" \
-d '{
"id": ["order_001", "order_002"],
"status": "archived"
}'SDK wrapper:
const updated = await orders.update({
id: "order_001",
status: "paid",
paidAt: "2026-04-23T10:00:00Z",
});
const updatedBatch = await orders.update(
["order_001", "order_002"],
{ status: "archived" },
);The SDK enforces a 1,000-record limit on bulk updates.
8.7 delete
delete removes one or more records. Deletion is a high-risk write operation — automation scripts should explicitly confirm the dataset and the ID.
curl -X POST "$RUNTIME_DOMAIN/api/$APP_CODE/$DATASET_CODE/delete" \
-H "Content-Type: application/json" \
-H "Cookie: $LOVRABET_COOKIE" \
-d '{"id":"order_001"}'Bulk delete:
curl -X POST "$RUNTIME_DOMAIN/api/$APP_CODE/$DATASET_CODE/delete" \
-H "Content-Type: application/json" \
-H "Cookie: $LOVRABET_COOKIE" \
-d '{"id":["order_001","order_002"]}'SDK wrapper:
await orders.delete("order_001");
await orders.delete({ id: ["order_001", "order_002"] });The SDK enforces a 1,000-record limit on bulk deletes. OpenAPI mode does not support delete; use WebAPI or Client API mode instead.
8.8 getSelectOptions
getSelectOptions turns dataset data into a { label, value } options array for frontend components.
curl -X POST "$RUNTIME_DOMAIN/api/$APP_CODE/$DATASET_CODE/getSelectOptions" \
-H "Content-Type: application/json" \
-H "Cookie: $LOVRABET_COOKIE" \
-d '{
"code": "id",
"label": "name"
}'SDK wrapper:
const options = await orders.getSelectOptions({
code: "id",
label: "name",
});It works well for Select, Radio, Checkbox, filters, and typeahead inputs. OpenAPI mode does not support getSelectOptions; use WebAPI or Client API mode instead.
8.9 excelExport
excelExport exports dataset query results to an Excel file, typically returning a downloadable file URL.
curl -X POST "$RUNTIME_DOMAIN/api/$APP_CODE/$DATASET_CODE/excelExport" \
-H "Content-Type: application/json" \
-H "Cookie: $LOVRABET_COOKIE" \
-d '{
"where": { "status": { "$eq": "paid" } },
"select": ["id", "orderNo", "status", "amount"],
"orderBy": [{ "createdAt": "desc" }]
}'SDK wrapper:
const fileUrl = await orders.excelExport({
where: { status: { $eq: "paid" } },
select: ["id", "orderNo", "status", "amount"],
orderBy: [{ createdAt: "desc" }],
});Reuse the page's filter conditions for exports so the on-screen query and the exported file always match. OpenAPI mode does not support excelExport; use WebAPI or Client API mode instead.