ObjectStackObjectStack

API Reference

Complete REST API reference for ObjectStack — all endpoints, request/response schemas, and service availability.

API Reference

ObjectStack exposes a fully typed REST API. All endpoints use JSON request/response bodies. The API is service-driven — routes are only available when the corresponding plugin is installed. Use the Discovery endpoint to determine what services are available at runtime.

Base URL: Configurable, defaults to /api/v1. All paths below are relative to the base URL.


Discovery

The discovery endpoint is the entry point for all clients. It returns the API version, available routes, service capabilities, and per-service status.

GET /api/v1

Returns the full discovery manifest.

Response:

{
  "name": "ObjectOS",
  "version": "1.0.0",
  "environment": "development",
  "routes": {
    "data": "/api/v1/data",
    "metadata": "/api/v1/meta",
    "analytics": "/api/v1/analytics",
    "auth": null,
    "workflow": null
  },
  "features": {
    "graphql": false,
    "search": false,
    "websockets": false,
    "files": false,
    "analytics": true,
    "ai": false,
    "workflow": false,
    "notifications": false,
    "i18n": false
  },
  "services": {
    "metadata": {
      "enabled": true,
      "status": "degraded",
      "route": "/api/v1/meta",
      "provider": "kernel",
      "message": "In-memory registry; DB persistence pending"
    },
    "data": { "enabled": true, "status": "available", "route": "/api/v1/data", "provider": "kernel" },
    "analytics": { "enabled": true, "status": "available", "route": "/api/v1/analytics" },
    "auth": { "enabled": false, "status": "unavailable", "message": "Install an auth plugin to enable" }
  },
  "locale": {
    "default": "en",
    "supported": ["en", "zh-CN"],
    "timezone": "UTC"
  }
}

GET /.well-known/objectstack

Alias for the discovery endpoint used by auto-discovery in the client SDK.

Service Status Values: available (fully operational), degraded (partial functionality), unavailable (not installed), stub (placeholder that throws errors)


Metadata

Retrieve and manage object schemas, metadata types, and UI views. Always available — provided by the kernel.

GET /meta

List all registered metadata types.

Response: { types: ["object", "view", "plugin", ...] }

GET /meta/:type

List all items of a metadata type.

ParameterLocationDescription
typepathMetadata type name (e.g. object, view)

Response: { type: "object", items: [{ name: "account", ... }, ...] }

GET /meta/:type/:name

Get a specific metadata item with optional ETag caching.

ParameterLocationDescription
typepathMetadata type name
namepathItem name (snake_case)
If-None-MatchheaderETag for conditional request

Response: { type: "object", name: "account", item: { ... } }
304 if ETag matches (not modified).

PUT /meta/:type/:name

Create or update a metadata item.

Body: { type: "object", name: "account", item: { ... } }
Response: { success: true }

GET /ui/view/:object/:type

Get an auto-generated UI view for an object.

ParameterLocationDescription
objectpathObject name (snake_case)
typepathlist or form

Response: Full ViewSchema definition with columns/fields derived from the object schema.


Data Operations

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

GET /data/:object

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

ParameterLocationDescription
objectpathObject name
$selectqueryComma-separated field names
$filterqueryFilter expression (OData-style or JSON)
$orderbyquerySort expression (e.g. -created_at)
$topqueryLimit (default: 20)
$skipqueryOffset

Response:

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

GET /data/:object/:id

Get a single record by ID.

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, errors, and optionally records.

POST /data/:object/createMany

Batch create multiple records.

Body: { records: [{ name: "A" }, { name: "B" }] }
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"] }


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"],
  "filters": [{ "member": "status", "operator": "equals", "values": ["active"] }],
  "limit": 100
}

Response:

{
  "data": [
    { "industry": "Technology", "revenue.sum": 150000, "count": 5 },
    { "industry": "Healthcare", "revenue.sum": 80000, "count": 3 }
  ],
  "annotation": {
    "measures": { "revenue.sum": { "title": "Revenue Sum", "type": "number" } },
    "dimensions": { "industry": { "title": "Industry", "type": "string" } }
  }
}

GET /analytics/meta

Get auto-generated cube metadata for all objects.

Response: Array of cube definitions with measures, dimensions, and time dimensions.

POST /analytics/sql

Execute a raw SQL analytics query (if supported by driver).


Package Management

Manage installed plugins/packages.

GET /packages

List installed packages.

POST /packages

Install a package from manifest.

Body: { manifest: { name: "plugin-auth", version: "1.0.0", ... } }

GET /packages/:id

Get package details.

DELETE /packages/:id

Uninstall a package.

PATCH /packages/:id/enable

Enable a disabled package.

PATCH /packages/:id/disable

Disable a package without uninstalling.


Authentication (Plugin Required)

These endpoints are only available when an auth plugin is installed. Check discovery.services.auth.enabled first.

POST /auth/login

Authenticate and receive a session token.

Body: { username: "admin", password: "secret" }
Response: { token: "jwt...", expiresAt: "...", user: { ... } }


Plugin-Provided Service Endpoints

The following endpoints become available when the corresponding plugin is installed and registered with the kernel. Use the discovery services map to check availability.

Workflow (/workflow) — Plugin Required

MethodEndpointDescription
GET/workflow/:object/configGet workflow configuration
GET/workflow/:object/:recordId/stateGet record's workflow state
POST/workflow/:object/:recordId/transitionExecute state transition
POST/workflow/:object/:recordId/approveApprove workflow step
POST/workflow/:object/:recordId/rejectReject workflow step

Automation (/automation) — Plugin Required

MethodEndpointDescription
POST/automation/triggerTrigger an automation flow

Views (/ui) — Plugin Required

MethodEndpointDescription
GET/ui/views?object=:objectList views for an object
GET/ui/views/:viewIdGet a view definition
POST/ui/viewsCreate a new view
PATCH/ui/views/:viewIdUpdate a view
DELETE/ui/views/:viewIdDelete a view

Realtime (/realtime) — Plugin Required

MethodEndpointDescription
POST/realtime/connectEstablish WebSocket/SSE connection
POST/realtime/disconnectClose connection
POST/realtime/subscribeSubscribe to channel
POST/realtime/unsubscribeUnsubscribe
POST/realtime/presenceSet presence
GET/realtime/presence/:channelGet channel presence

Notifications (/notifications) — Plugin Required

MethodEndpointDescription
GET/notificationsList notifications
POST/notifications/readMark as read
POST/notifications/read-allMark all as read
POST/notifications/devicesRegister device
DELETE/notifications/devices/:idUnregister device
GET/notifications/preferencesGet preferences
PATCH/notifications/preferencesUpdate preferences

AI (/ai) — Plugin Required

MethodEndpointDescription
POST/ai/nlqNatural language → query
POST/ai/chatAI chat conversation
POST/ai/suggestGet value suggestions
POST/ai/insightsGet data insights

i18n (/i18n) — Plugin Required

MethodEndpointDescription
GET/i18n/localesList available locales
GET/i18n/translations?locale=:localeGet translation bundle
GET/i18n/labels/:object?locale=:localeGet field labels

GraphQL (/graphql) — Plugin Required

MethodEndpointDescription
POST/graphqlExecute GraphQL query/mutation

File Storage (/storage) — Plugin Required

MethodEndpointDescription
POST/storage/uploadUpload a file
GET/storage/:idDownload a file
DELETE/storage/:idDelete a file

Error Handling

All error responses follow a standardized format:

{
  "error": {
    "code": "resource_not_found",
    "message": "Record not found: account/123",
    "httpStatus": 404,
    "category": "request",
    "retryable": false,
    "details": {}
  }
}

Error Codes

CodeHTTPCategoryRetryableDescription
validation_error400validationNoInput validation failed
invalid_query400validationNoMalformed query
unauthenticated401authNoAuthentication required
permission_denied403authNoInsufficient permissions
resource_not_found404requestNoResource does not exist
conflict409requestNoResource conflict (e.g. duplicate)
rate_limit_exceeded429rate_limitYesToo many requests
internal_error500serverYesServer error
service_unavailable503serverYesService temporarily unavailable

Protocol Types (Zod)

All request/response schemas are defined as Zod schemas in @objectstack/spec/api and can be used for both runtime validation and TypeScript type inference.

import { 
  FindDataRequestSchema, 
  FindDataResponseSchema,
  type FindDataRequest,
  type FindDataResponse,
} from '@objectstack/spec/api';

// Runtime validation
const request = FindDataRequestSchema.parse({ object: 'account', query: { ... } });

// TypeScript type
const response: FindDataResponse = await protocol.findData(request);

See the Protocol Reference for the complete list of 57 protocol methods and their Zod schemas.


Next Steps

On this page