Skip to content

Latest commit

 

History

History
220 lines (158 loc) · 6.76 KB

File metadata and controls

220 lines (158 loc) · 6.76 KB
title Data API
description REST endpoints for CRUD, batch operations, record cloning, and analytics queries.

Data API

Record CRUD, batch operations, and analytics queries over REST. All paths are relative to the base URL (defaults to /api/v1) — see the API Overview for discovery and service availability.

Data Operations

CRUD operations on any object. Always available — provided by the kernel.

GET /data/:object

Query records with filtering, sorting, selection, and pagination.

Parameter Location Description
object path Object name
select query Comma-separated field names
filter query Filter expression (JSON). filters also accepted for backward compatibility.
sort query Sort expression (e.g. name asc or -created_at)
top query Max records to return. No default — omitting it returns all matching records.
skip query Offset
expand query Comma-separated list of relations to eager-load
search query Full-text search query

Note: OData-style $-prefixed parameters ($filter, $select, $orderby, $top, $skip, $expand, $count, $search) are also accepted directly on this same endpoint as aliases — they're normalized internally to the parameter names above. There is no separate standalone OData endpoint.

Response:

{
  "object": "account",
  "records": [{ "id": "1", "name": "Acme Corp", ... }],
  "total": 42,
  "hasMore": true
}

GET /data/:object/:id

Get a single record by ID. Only select and expand query parameters are allowed; all other parameters are discarded.

Parameter Location Description
object path Object name
id path Record ID
select query Comma-separated field names to include
expand query Comma-separated list of relations to eager-load

Response: { object: "account", id: "1", record: { ... } }

POST /data/:object

Create a new record.

Body: { name: "Acme Corp", industry: "Technology" }
Response: { object: "account", id: "1", record: { ... } }

PATCH /data/:object/:id

Update an existing record (partial update).

Body: { industry: "Healthcare" }
Response: { object: "account", id: "1", record: { ... } }

DELETE /data/:object/:id

Delete a record.

Response: { object: "account", id: "1", success: true }


Batch Operations

Efficient bulk operations. Always available.

POST /data/:object/batch

Execute a batch operation (create / update / upsert / delete) on multiple records.

Body:

{
  "operation": "update",
  "records": [
    { "id": "1", "data": { "status": "active" } },
    { "id": "2", "data": { "status": "active" } }
  ],
  "options": {
    "atomic": true,
    "returnRecords": true,
    "continueOnError": false,
    "validateOnly": false
  }
}

Response: BatchUpdateResponse with succeeded, failed, total, and a per-record results array. Each entry in results has id, success, an optional errors array, and optional data (the full record, present when returnRecords is true).

POST /data/:object/createMany

Batch create multiple records.

Body: a bare array of records — [{ name: "A" }, { name: "B" }]. The REST handler reads the request body directly as the records array, so do not wrap it in { records: [...] }.
Response: { object: "account", records: [...], count: 2 }

POST /data/:object/updateMany

Batch update multiple records.

Body:

{
  "records": [
    { "id": "1", "data": { "status": "active" } },
    { "id": "2", "data": { "status": "closed" } }
  ],
  "options": { "atomic": false }
}

POST /data/:object/deleteMany

Batch delete records by ID list.

Body: { ids: ["1", "2", "3"] }


POST /data/:object/:id/clone

Clone a record. Reads the source, drops engine-owned columns (id, the audit fields, autonumbers, and computed formula/summary values) so they are re-derived, applies any caller overrides, and inserts the copy. Shallow by design — it duplicates the record's own fields, not its child records.

Gated by the object's enable.clone capability (default true); an object with enable.clone: false returns 403 CLONE_DISABLED.

Body (optional): { "overrides": { "name": "Acme (Copy)" } } — applied on top of the copied values (a bare field map is also accepted). The natural place to set a new name or clear a unique field.

Response 201: { object, id, sourceId, record }


Analytics

Semantic BI queries using a cube-style API. Available when the analytics service is enabled.

POST /analytics/query

Execute an analytics query.

Body:

{
  "cube": "account",
  "measures": ["revenue.sum", "count"],
  "dimensions": ["industry"],
  "where": { "status": "active" },
  "limit": 100
}
Filtering uses the canonical Query DSL `where` object (the same MongoDB-style `FilterCondition` accepted by `find()`), not a `filters` array.

Response: the runtime dispatcher wraps the AnalyticsResult as { success: true, data: { rows, fields, sql?, totals? } }:

{
  "success": true,
  "data": {
    "rows": [
      { "industry": "Technology", "revenue.sum": 150000, "count": 5 },
      { "industry": "Healthcare", "revenue.sum": 80000, "count": 3 }
    ],
    "fields": [
      { "name": "industry", "type": "string", "label": "Industry" },
      { "name": "revenue.sum", "type": "number", "label": "Revenue Sum", "format": "$0,0" },
      { "name": "count", "type": "number", "label": "Count" }
    ],
    "sql": "SELECT ..."
  }
}

GET /analytics/meta

Get metadata for all registered cubes. Cubes are explicitly defined (via defineCube or the analytics service's cubes config) — a cube referenced by a query that isn't yet registered is lazily auto-inferred from that query's shape, but metadata isn't proactively generated for every object.

Pass ?cube=<name> to filter the listing to a single cube (this is what client.analytics.meta(cube) sends).

Response: { success: true, data: [...] } where data is an array of cube definitions with measures and dimensions (time-based dimensions are dimensions entries with type: "time").

POST /analytics/sql

Generate the SQL for a given analytics query without executing it (dry-run/debug). Accepts the same body shape as /analytics/query; support depends on the underlying driver/strategy.

Response: { success: true, data: { sql: string, params: unknown[] } }


See also