Plugin Rest Api — API Protocol reference Defines the schema for REST API plugins that register Discovery, Metadata, Data CRUD, Batch, and Permission routes with the HTTP Dispatcher.
REST API Plugin Protocol
Defines the schema for REST API plugins that register Discovery, Metadata,
Data CRUD, Batch, and Permission routes with the HTTP Dispatcher.
This plugin type implements Phase 2 of the API Protocol implementation plan,
providing standardized REST endpoints with:
Request validation middleware using Zod schemas
Response envelope wrapping with BaseResponseSchema
Error handling using ApiErrorSchema
OpenAPI documentation auto-generation
Features:
Route registration for core API endpoints
Automatic schema-based validation
Standardized request/response envelopes
OpenAPI/Swagger documentation generation
Architecture Alignment:
Salesforce: REST API with metadata and data CRUD
Microsoft Dynamics: Web API with entity operations
Strapi: Auto-generated REST endpoints from schemas
Serving routes from a plugin (imperative http.server mount)
// Routes are mounted in CODE — resolve the `http.server` service from the
// plugin context and register handlers on `kernel:ready` (the service is
// registered by plugin-hono-server; `examples/app-showcase`'s
// recalc-endpoint is a real consumer of this exact shape). The worked
// manifest example that used to sit here declared `contributes.routes`,
// which was removed in @objectstack/spec 17 (commit bc56e1881): nothing ever read
// it, so every route it showed parsed cleanly and served nothing.
class RestApiPlugin {
name = 'rest_api' ;
async init ( ctx : PluginContext ) {
ctx. hook ( 'kernel:ready' , async () => {
const server = await ctx. getService < IHttpServer >( 'http.server' );
server. get ( '/api/v1/discovery' , ( req , res ) => { ... });
server. post ( '/api/v1/data/:object' , ( req , res ) => { ... });
});
}
}
A declarative endpoint over a pipeline the platform already runs
(query/return records, trigger a flow) is defineStack({ apis }) instead —
no plugin code at all.
Source: packages/spec/src/api/plugin-rest-api.zod.ts
import { ErrorHandlingConfigSchema, OpenApiGenerationConfigSchema, RequestValidationConfigSchema, ResponseEnvelopeConfigSchema, RestApiEndpointSchema, RestApiPluginConfigSchema, RestApiRouteCategory, RestApiRouteRegistrationSchema, ValidationMode } from '@objectstack/spec/api' ;
import type { ErrorHandlingConfig, OpenApiGenerationConfig, RequestValidationConfig, ResponseEnvelopeConfig, RestApiEndpoint, RestApiPluginConfig, RestApiRouteCategory, RestApiRouteRegistration, ValidationMode } from '@objectstack/spec/api' ;
// Validate data
const result = ErrorHandlingConfigSchema. parse (data);
Property Type Required Description enabled booleanoptional (default: true) Enable standardized error handling includeStackTrace booleanoptional (default: false) Include stack traces in error responses logErrors booleanoptional (default: true) Log errors to system logger exposeInternalErrors booleanoptional (default: false) Expose internal error details in responses includeRequestId booleanoptional (default: true) Include requestId in error responses includeTimestamp booleanoptional (default: true) Include timestamp in error responses includeDocumentation booleanoptional (default: true) Include documentation URLs for errors documentationBaseUrl stringoptional Base URL for error documentation customErrorMessages Record<string, string>optional Custom error messages by error code redactFields string[]optional Field names to redact from error details
Property Type Required Description enabled booleanoptional (default: true) Enable automatic OpenAPI documentation generation version Enum<'3.0.0' | '3.0.1' | '3.0.2' | '3.0.3' | '3.1.0'>optional (default: "3.0.3") OpenAPI specification version title stringoptional (default: "ObjectStack API") API title description stringoptional API description apiVersion stringoptional (default: "1.0.0") API version outputPath stringoptional (default: "/api/docs/openapi.json") URL path to serve OpenAPI JSON uiPath stringoptional (default: "/api/docs") URL path to serve documentation UI uiFramework Enum<'swagger-ui' | 'redoc' | 'rapidoc' | 'elements'>optional (default: "swagger-ui") Documentation UI framework includeInternal booleanoptional (default: false) Include internal endpoints in documentation generateSchemas booleanoptional (default: true) Auto-generate schemas from Zod definitions includeExamples booleanoptional (default: true) Include request/response examples servers { url: string; description?: string }[]optional Server URLs for API contact { name?: string; url?: string; email?: string }optional API contact information license { name: string; url?: string }optional API license information securitySchemes Record<string, { type: Enum<'apiKey' | 'http' | 'oauth2' | 'openIdConnect'>; scheme?: string; bearerFormat?: string }>optional Security scheme definitions
Property Type Required Description url string✅ Server URL description stringoptional Server description
Property Type Required Description name string✅ License name url stringoptional License URL
Property Type Required Description enabled booleanoptional (default: true) Enable automatic request validation mode Enum<'strict' | 'permissive' | 'strip'>optional (default: "strict") How to handle validation errors validateBody booleanoptional (default: true) Validate request body against schema validateQuery booleanoptional (default: true) Validate query string parameters validateParams booleanoptional (default: true) Validate URL path parameters validateHeaders booleanoptional (default: false) Validate request headers includeFieldErrors booleanoptional (default: true) Include field-level error details in response errorPrefix stringoptional Custom prefix for validation error messages schemaRegistry stringoptional Schema registry name to use for validation
Property Type Required Description enabled booleanoptional (default: true) Enable automatic response envelope wrapping includeMetadata booleanoptional (default: true) Include meta object in responses includeTimestamp booleanoptional (default: true) Include timestamp in response metadata includeRequestId booleanoptional (default: true) Include requestId in response metadata includeDuration booleanoptional (default: false) Include request duration in ms includeTraceId booleanoptional (default: false) Include distributed traceId customMetadata Record<string, any>optional Additional metadata fields to include skipIfWrapped booleanoptional (default: true) Skip wrapping if response already has success field
Property Type Required Description method Enum<'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS'>✅ HTTP method for this endpoint path string✅ URL path pattern (e.g., /api/v1/data/:object/:id) handler string✅ Protocol method name or handler identifier category Enum<'discovery' | 'metadata' | 'data' | 'batch' | 'permission' | 'analytics' | 'automation' | 'ui' | 'realtime' | 'notification' | 'ai' | 'i18n'>✅ Route category public booleanoptional (default: false) Is publicly accessible without authentication permissions string[]optional Required permissions (e.g., ["data.read", "object.account.read"]) summary stringoptional Short description for OpenAPI description stringoptional Detailed description for OpenAPI tags string[]optional OpenAPI tags for grouping requestSchema stringoptional Request schema name (for validation) responseSchema stringoptional Response schema name (for documentation) timeoutMs integeroptional Request timeout in milliseconds rateLimit stringoptional Rate limit policy name cacheable booleanoptional (default: false) Whether response can be cached cacheTtlSeconds integeroptional Cache TTL in seconds timeout neveroptional [REMOVED] RestApiEndpoint.timeout was renamed to timeoutMs in @objectstack/spec 17 — the unit of a duration-shaped number lives in the key name, not only in the describe prose, and the neighbouring cache TTL two lines below is in SECONDS. Rename the key to timeoutMs; the value (milliseconds) is unchanged. cacheTtl neveroptional [REMOVED] RestApiEndpoint.cacheTtl was renamed to cacheTtlSeconds in @objectstack/spec 17 — the unit of a duration-shaped number lives in the key name, not only in the describe prose, and the neighbouring request timeout two lines above is in MILLISECONDS. Rename the key to cacheTtlSeconds; the value (seconds) is unchanged. handlerStatus neveroptional [REMOVED] RestApiEndpoint.handlerStatus was removed in @objectstack/spec 17 (ADR-0049 enforce-or-remove) — nothing ever read it: no registrar, dispatcher or adapter consulted the key, so an endpoint declared stub or planned was served exactly like an implemented one, and the 501 NOT_IMPLEMENTED its docstring promised is raised by the declarative-endpoint executor for a target it cannot serve, never from this field. Delete the key. An endpoint that has no handler yet is simply not registered; a declared-but-unbuilt route answering 501 is not a platform capability (ruling record, 2026-09-01).
Property Type Required Description enabled booleanoptional (default: true) Enable REST API plugin basePath stringoptional (default: "/api") Base path for all API routes version stringoptional (default: "v1") API version identifier routes { prefix: string; service: string; category: Enum<'discovery' | 'metadata' | 'data' | 'batch' | 'permission' | 'analytics' | …>; methods?: string[]; … }[]✅ Route registrations validation { enabled?: boolean; mode?: Enum<'strict' | 'permissive' | 'strip'>; validateBody?: boolean; validateQuery?: boolean; … }optional Request validation configuration responseEnvelope { enabled?: boolean; includeMetadata?: boolean; includeTimestamp?: boolean; includeRequestId?: boolean; … }optional Response envelope configuration errorHandling { enabled?: boolean; includeStackTrace?: boolean; logErrors?: boolean; exposeInternalErrors?: boolean; … }optional Error handling configuration openApi { enabled?: boolean; version?: Enum<'3.0.0' | '3.0.1' | '3.0.2' | '3.0.3' | '3.1.0'>; title?: string; description?: string; … }optional OpenAPI documentation configuration globalMiddleware { name: string; type: Enum<'authentication' | 'authorization' | 'logging' | 'validation' | 'transformation' | 'error' | 'custom'>; enabled?: boolean; order?: integer; … }[]optional Global middleware stack cors { enabled?: boolean; origins?: string[]; methods?: Enum<'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS'>[]; credentials?: boolean }optional CORS configuration performance { enableCompression?: boolean; enableETag?: boolean; enableCaching?: boolean; defaultCacheTtlSeconds?: integer }optional Performance optimization settings
Property Type Required Description prefix string✅ URL path prefix for this route group service string✅ Core service name (metadata, data, auth, etc.) category Enum<'discovery' | 'metadata' | 'data' | 'batch' | 'permission' | 'analytics' | …>✅ Primary category for this route group methods string[]optional Protocol method names implemented endpoints { method: Enum<'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS'>; path: string; handler: string; category: Enum<'discovery' | 'metadata' | 'data' | 'batch' | 'permission' | 'analytics' | …>; … }[]optional Endpoint definitions middleware { name: string; type: Enum<'authentication' | 'authorization' | 'logging' | 'validation' | 'transformation' | 'error' | 'custom'>; enabled?: boolean; order?: integer; … }[]optional Middleware stack for this route group authRequired booleanoptional (default: true) Whether authentication is required by default documentation { title?: string; description?: string; tags?: string[] }optional Documentation metadata for this route group
Property Type Required Description enabled booleanoptional (default: true) Enable automatic request validation mode Enum<'strict' | 'permissive' | 'strip'>optional (default: "strict") How to handle validation errors validateBody booleanoptional (default: true) Validate request body against schema validateQuery booleanoptional (default: true) Validate query string parameters validateParams booleanoptional (default: true) Validate URL path parameters validateHeaders booleanoptional (default: false) Validate request headers includeFieldErrors booleanoptional (default: true) Include field-level error details in response errorPrefix stringoptional Custom prefix for validation error messages schemaRegistry stringoptional Schema registry name to use for validation
Property Type Required Description enabled booleanoptional (default: true) Enable automatic response envelope wrapping includeMetadata booleanoptional (default: true) Include meta object in responses includeTimestamp booleanoptional (default: true) Include timestamp in response metadata includeRequestId booleanoptional (default: true) Include requestId in response metadata includeDuration booleanoptional (default: false) Include request duration in ms includeTraceId booleanoptional (default: false) Include distributed traceId customMetadata Record<string, any>optional Additional metadata fields to include skipIfWrapped booleanoptional (default: true) Skip wrapping if response already has success field
Property Type Required Description enabled booleanoptional (default: true) Enable standardized error handling includeStackTrace booleanoptional (default: false) Include stack traces in error responses logErrors booleanoptional (default: true) Log errors to system logger exposeInternalErrors booleanoptional (default: false) Expose internal error details in responses includeRequestId booleanoptional (default: true) Include requestId in error responses includeTimestamp booleanoptional (default: true) Include timestamp in error responses includeDocumentation booleanoptional (default: true) Include documentation URLs for errors documentationBaseUrl stringoptional Base URL for error documentation customErrorMessages Record<string, string>optional Custom error messages by error code redactFields string[]optional Field names to redact from error details
Property Type Required Description enabled booleanoptional (default: true) Enable automatic OpenAPI documentation generation version Enum<'3.0.0' | '3.0.1' | '3.0.2' | '3.0.3' | '3.1.0'>optional (default: "3.0.3") OpenAPI specification version title stringoptional (default: "ObjectStack API") API title description stringoptional API description apiVersion stringoptional (default: "1.0.0") API version outputPath stringoptional (default: "/api/docs/openapi.json") URL path to serve OpenAPI JSON uiPath stringoptional (default: "/api/docs") URL path to serve documentation UI uiFramework Enum<'swagger-ui' | 'redoc' | 'rapidoc' | 'elements'>optional (default: "swagger-ui") Documentation UI framework includeInternal booleanoptional (default: false) Include internal endpoints in documentation generateSchemas booleanoptional (default: true) Auto-generate schemas from Zod definitions includeExamples booleanoptional (default: true) Include request/response examples servers { url: string; description?: string }[]optional Server URLs for API contact { name?: string; url?: string; email?: string }optional API contact information license { name: string; url?: string }optional API license information securitySchemes Record<string, { type: Enum<'apiKey' | 'http' | 'oauth2' | 'openIdConnect'>; scheme?: string; bearerFormat?: string }>optional Security scheme definitions
Property Type Required Description name string✅ Middleware name (snake_case) type Enum<'authentication' | 'authorization' | 'logging' | 'validation' | 'transformation' | 'error' | 'custom'>✅ Middleware type enabled booleanoptional (default: true) Whether middleware is enabled order integeroptional (default: 100) Execution order priority config Record<string, any>optional Middleware configuration object paths { include?: string[]; exclude?: string[] }optional Path filtering
Property Type Required Description enableCompression booleanoptional (default: true) Enable response compression enableETag booleanoptional (default: true) Enable ETag generation enableCaching booleanoptional (default: true) Enable HTTP caching defaultCacheTtlSeconds integeroptional (default: 300) Default cache TTL in seconds defaultCacheTtl neveroptional [REMOVED] RestApiPluginConfig.performance.defaultCacheTtl was renamed to defaultCacheTtlSeconds in @objectstack/spec 17 — the unit of a duration-shaped number lives in the key name, not only in the describe prose. Rename the key to defaultCacheTtlSeconds; the value (seconds) is unchanged.
discovery
metadata
data
batch
permission
analytics
automation
ui
realtime
notification
ai
i18n
Property Type Required Description prefix string✅ URL path prefix for this route group service string✅ Core service name (metadata, data, auth, etc.) category Enum<'discovery' | 'metadata' | 'data' | 'batch' | 'permission' | 'analytics' | 'automation' | 'ui' | 'realtime' | 'notification' | 'ai' | 'i18n'>✅ Primary category for this route group methods string[]optional Protocol method names implemented endpoints { method: Enum<'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS'>; path: string; handler: string; category: Enum<'discovery' | 'metadata' | 'data' | 'batch' | 'permission' | 'analytics' | …>; … }[]optional Endpoint definitions middleware { name: string; type: Enum<'authentication' | 'authorization' | 'logging' | 'validation' | 'transformation' | 'error' | 'custom'>; enabled?: boolean; order?: integer; … }[]optional Middleware stack for this route group authRequired booleanoptional (default: true) Whether authentication is required by default documentation { title?: string; description?: string; tags?: string[] }optional Documentation metadata for this route group
Property Type Required Description method Enum<'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS'>✅ HTTP method for this endpoint path string✅ URL path pattern (e.g., /api/v1/data/:object/:id) handler string✅ Protocol method name or handler identifier category Enum<'discovery' | 'metadata' | 'data' | 'batch' | 'permission' | 'analytics' | …>✅ Route category public booleanoptional (default: false) Is publicly accessible without authentication permissions string[]optional Required permissions (e.g., ["data.read", "object.account.read"]) summary stringoptional Short description for OpenAPI description stringoptional Detailed description for OpenAPI tags string[]optional OpenAPI tags for grouping requestSchema stringoptional Request schema name (for validation) responseSchema stringoptional Response schema name (for documentation) timeoutMs integeroptional Request timeout in milliseconds rateLimit stringoptional Rate limit policy name cacheable booleanoptional (default: false) Whether response can be cached cacheTtlSeconds integeroptional Cache TTL in seconds timeout neveroptional [REMOVED] RestApiEndpoint.timeout was renamed to timeoutMs in @objectstack/spec 17 — the unit of a duration-shaped number lives in the key name, not only in the describe prose, and the neighbouring cache TTL two lines below is in SECONDS. Rename the key to timeoutMs; the value (milliseconds) is unchanged. cacheTtl neveroptional [REMOVED] RestApiEndpoint.cacheTtl was renamed to cacheTtlSeconds in @objectstack/spec 17 — the unit of a duration-shaped number lives in the key name, not only in the describe prose, and the neighbouring request timeout two lines above is in MILLISECONDS. Rename the key to cacheTtlSeconds; the value (seconds) is unchanged. handlerStatus neveroptional [REMOVED] RestApiEndpoint.handlerStatus was removed in @objectstack/spec 17 (ADR-0049 enforce-or-remove) — nothing ever read it: no registrar, dispatcher or adapter consulted the key, so an endpoint declared stub or planned was served exactly like an implemented one, and the 501 NOT_IMPLEMENTED its docstring promised is raised by the declarative-endpoint executor for a target it cannot serve, never from this field. Delete the key. An endpoint that has no handler yet is simply not registered; a declared-but-unbuilt route answering 501 is not a platform capability (ruling record, 2026-09-01).
Property Type Required Description name string✅ Middleware name (snake_case) type Enum<'authentication' | 'authorization' | 'logging' | 'validation' | 'transformation' | 'error' | 'custom'>✅ Middleware type enabled booleanoptional (default: true) Whether middleware is enabled order integeroptional (default: 100) Execution order priority config Record<string, any>optional Middleware configuration object paths { include?: string[]; exclude?: string[] }optional Path filtering
Property Type Required Description title stringoptional Route group title description stringoptional Route group description tags string[]optional OpenAPI tags