Protocol
Protocol protocol schemas
Source: packages/spec/src/api/protocol.zod.ts
TypeScript Usage
import { AiAgentCapabilitiesSchema, AiAgentChatRequestSchema, AiAgentSummarySchema, AiAgentsResponseSchema, AiChatRequestSchema, AiChatResponseSchema, AiCompleteRequestSchema, AiConversationSchema, AiMessageSchema, AiModelsResponseSchema, AiPendingActionSchema, AiPendingActionStatusSchema, AiStreamChunkSchema, ApproveAiPendingActionResponseSchema, AutomationActionsResponseSchema, AutomationTriggerRequestSchema, AutomationTriggerResponseSchema, BatchDataRequestSchema, BatchDataResponseSchema, CheckPermissionRequestSchema, CheckPermissionResponseSchema, CreateAiConversationRequestSchema, CreateDataRequestSchema, CreateDataResponseSchema, CreateManyDataRequestSchema, CreateManyDataResponseSchema, DeleteDataRequestSchema, DeleteDataResponseSchema, DeleteManyDataRequestSchema, DeleteManyDataResponseSchema, DeleteMetaItemRequestSchema, DeleteMetaItemResponseSchema, DisablePackageRequestSchema, DisablePackageResponseSchema, EnablePackageRequestSchema, EnablePackageResponseSchema, FindDataRequestSchema, FindDataResponseSchema, GetDataRequestSchema, GetDataResponseSchema, GetDiscoveryRequestSchema, GetDiscoveryResponseSchema, GetEffectivePermissionsRequestSchema, GetEffectivePermissionsResponseSchema, GetFieldLabelsRequestSchema, GetFieldLabelsResponseSchema, GetLocalesRequestSchema, GetLocalesResponseSchema, GetMetaItemCachedRequestSchema, GetMetaItemCachedResponseSchema, GetMetaItemLayeredResponseSchema, GetMetaItemRequestSchema, GetMetaItemResponseSchema, GetMetaItemsRequestSchema, GetMetaItemsResponseSchema, GetMetaTypesRequestSchema, GetMetaTypesResponseSchema, GetNotificationPreferencesRequestSchema, GetNotificationPreferencesResponseSchema, GetObjectPermissionsRequestSchema, GetObjectPermissionsResponseSchema, GetPackageRequestSchema, GetPackageResponseSchema, GetPresenceRequestSchema, GetPresenceResponseSchema, GetTranslationsRequestSchema, GetTranslationsResponseSchema, GetUiViewRequestSchema, GetUiViewResponseSchema, HttpFindQueryParamsSchema, InstallPackageRequestSchema, InstallPackageResponseSchema, ListAiConversationsRequestSchema, ListAiConversationsResponseSchema, ListAiPendingActionsRequestSchema, ListAiPendingActionsResponseSchema, ListNotificationsRequestSchema, ListNotificationsResponseSchema, ListPackagesRequestSchema, ListPackagesResponseSchema, MarkAllNotificationsReadRequestSchema, MarkAllNotificationsReadResponseSchema, MarkNotificationsReadRequestSchema, MarkNotificationsReadResponseSchema, NotificationSchema, NotificationPreferencesSchema, PublishMetaItemResponseSchema, RealtimeConnectRequestSchema, RealtimeConnectResponseSchema, RealtimeDisconnectRequestSchema, RealtimeDisconnectResponseSchema, RealtimeSubscribeRequestSchema, RealtimeSubscribeResponseSchema, RealtimeUnsubscribeRequestSchema, RealtimeUnsubscribeResponseSchema, RegisterDeviceRequestSchema, RegisterDeviceResponseSchema, RejectAiPendingActionResponseSchema, RuntimeAuthoringIssueSchema, SaveMetaItemRequestSchema, SaveMetaItemResponseSchema, SetPresenceRequestSchema, SetPresenceResponseSchema, UninstallPackageRequestSchema, UninstallPackageResponseSchema, UnregisterDeviceRequestSchema, UnregisterDeviceResponseSchema, UpdateAiConversationRequestSchema, UpdateDataRequestSchema, UpdateDataResponseSchema, UpdateManyDataRequestSchema, UpdateManyDataResponseSchema, UpdateNotificationPreferencesRequestSchema, UpdateNotificationPreferencesResponseSchema, ValidateDataIssueSchema, ValidateDataRequestSchema, ValidateDataResponseSchema } from '@objectstack/spec/api';
import type { AiAgentCapabilities, AiAgentChatRequest, AiAgentSummary, AiAgentsResponse, AiChatRequest, AiChatResponse, AiCompleteRequest, AiConversation, AiMessage, AiModelsResponse, AiPendingAction, AiPendingActionStatus, AiStreamChunk, ApproveAiPendingActionResponse, AutomationActionsResponse, AutomationTriggerRequest, AutomationTriggerResponse, BatchDataRequest, BatchDataResponse, CheckPermissionRequest, CheckPermissionResponse, CreateAiConversationRequest, CreateDataRequest, CreateDataResponse, CreateManyDataRequest, CreateManyDataResponse, DeleteDataRequest, DeleteDataResponse, DeleteManyDataRequest, DeleteManyDataResponse, DeleteMetaItemRequest, DeleteMetaItemResponse, DisablePackageRequest, DisablePackageResponse, EnablePackageRequest, EnablePackageResponse, FindDataRequest, FindDataResponse, GetDataRequest, GetDataResponse, GetDiscoveryRequest, GetDiscoveryResponse, GetEffectivePermissionsRequest, GetEffectivePermissionsResponse, GetFieldLabelsRequest, GetFieldLabelsResponse, GetLocalesRequest, GetLocalesResponse, GetMetaItemCachedRequest, GetMetaItemCachedResponse, GetMetaItemLayeredResponse, GetMetaItemRequest, GetMetaItemResponse, GetMetaItemsRequest, GetMetaItemsResponse, GetMetaTypesRequest, GetMetaTypesResponse, GetNotificationPreferencesRequest, GetNotificationPreferencesResponse, GetObjectPermissionsRequest, GetObjectPermissionsResponse, GetPackageRequest, GetPackageResponse, GetPresenceRequest, GetPresenceResponse, GetTranslationsRequest, GetTranslationsResponse, GetUiViewRequest, GetUiViewResponse, InstallPackageRequest, InstallPackageResponse, ListAiConversationsRequest, ListAiConversationsResponse, ListAiPendingActionsRequest, ListAiPendingActionsResponse, ListNotificationsRequest, ListNotificationsResponse, ListPackagesRequest, ListPackagesResponse, MarkAllNotificationsReadRequest, MarkAllNotificationsReadResponse, MarkNotificationsReadRequest, MarkNotificationsReadResponse, Notification, NotificationPreferences, PublishMetaItemResponse, RealtimeConnectRequest, RealtimeConnectResponse, RealtimeDisconnectRequest, RealtimeDisconnectResponse, RealtimeSubscribeRequest, RealtimeSubscribeResponse, RealtimeUnsubscribeRequest, RealtimeUnsubscribeResponse, RegisterDeviceRequest, RegisterDeviceResponse, RejectAiPendingActionResponse, RuntimeAuthoringIssue, SaveMetaItemRequest, SaveMetaItemResponse, SetPresenceRequest, SetPresenceResponse, UninstallPackageRequest, UninstallPackageResponse, UnregisterDeviceRequest, UnregisterDeviceResponse, UpdateAiConversationRequest, UpdateDataRequest, UpdateDataResponse, UpdateManyDataRequest, UpdateManyDataResponse, UpdateNotificationPreferencesRequest, UpdateNotificationPreferencesResponse, ValidateDataIssue, ValidateDataRequest, ValidateDataResponse } from '@objectstack/spec/api';
// Validate data
const result = AiAgentCapabilitiesSchema.parse(data);AiAgentCapabilities
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| authoring | boolean | ✅ | Authors app metadata (objects/views/flows) |
| canvas | boolean | ✅ | Drives the Live Canvas split view (ADR-0037) |
| debug | boolean | ✅ | Exposes the build-doctor debug drawer |
| resume | boolean | ✅ | Turns resume durable multi-step runs (ADR-0013) |
AiAgentChatRequest
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| messages | ({ role: Enum<'system' | 'user' | 'assistant' | 'tool'>; content?: any; parts?: any[] } & Record<string, any>)[] | ✅ | Conversation messages (at least one) |
| context | Record<string, any> | optional | Agent context (app, object, record, …) |
| options | Record<string, any> | optional | Request options (model, temperature, …) |
AiAgentSummary
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| name | string | ✅ | Agent name — the :agentName path segment |
| label | string | ✅ | Display label |
| role | string | ✅ | Agent role |
| capabilities | { authoring: boolean; canvas: boolean; debug: boolean; resume: boolean } | ✅ | Capability set implied by the agent surface |
AiAgentsResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| agents | { name: string; label: string; role: string; capabilities: object }[] | ✅ | Agents this caller may chat with |
AiChatRequest
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| messages | ({ role: Enum<'system' | 'user' | 'assistant' | 'tool'>; content?: any; parts?: any[] } & Record<string, any>)[] | ✅ | Conversation messages (at least one) |
| system | string | optional | System prompt, prepended as a system message |
| model | string | optional | Model id override |
| temperature | number | optional | Sampling temperature |
| maxTokens | integer | optional | Maximum tokens to generate |
| stream | boolean | optional | false → JSON response; otherwise the UI Message Stream Protocol |
| conversationId | string | optional | Conversation to persist this turn into (auto-created when omitted) |
| turnId | string | optional | Stable per-turn idempotency key (ADR-0013 D1) |
| options | Record<string, any> | optional | Legacy nested request options |
AiChatResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| content | string | ✅ | Generated text |
| model | string | optional | Model that produced it |
| toolCalls | any[] | optional | Tool calls the model requested (Vercel ToolCallPart) |
| usage | { promptTokens: number; completionTokens: number; totalTokens: number } | optional | Token usage |
| conversationId | string | optional | Conversation the turn was persisted into |
AiCompleteRequest
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| prompt | string | ✅ | Prompt text |
| options | Record<string, any> | optional | Request options (model, temperature, maxTokens, …) |
AiConversation
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| id | string | ✅ | Conversation id |
| title | string | optional | Title / summary |
| agentId | string | optional | Agent this conversation is bound to |
| userId | string | optional | Owning user |
| messages | ({ role: Enum<'system' | 'user' | 'assistant' | 'tool'>; content?: any; parts?: any[] } & Record<string, any>)[] | ✅ | Message history |
| createdAt | string | ✅ | Creation timestamp (ISO 8601) |
| updatedAt | string | ✅ | Last update timestamp (ISO 8601) |
| metadata | Record<string, any> | optional | Conversation metadata |
AiMessage
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| role | Enum<'system' | 'user' | 'assistant' | 'tool'> | ✅ | Message role |
| content | any | optional | Message content: a string, or an array of content parts |
| parts | any[] | optional | Vercel AI SDK v6 message parts (alternative to content) |
AiModelsResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| models | (string | { id: string; label: string; default: boolean })[] | ✅ | Models this environment offers |
| defaultModel | string | optional | Default model id, when the service reports one |
AiPendingAction
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| id | string | ✅ | Pending action id |
| object_name | string | ✅ | Object the action targets |
| action_name | string | ✅ | Action name |
| tool_name | string | ✅ | Tool that would execute it |
| tool_input | string | ✅ | Serialized tool input |
| status | Enum<'pending' | 'approved' | 'executed' | 'failed' | 'rejected'> | ✅ | Lifecycle status |
| result | string | optional | Serialized result, once executed |
| error | string | optional | Failure message, when status is failed |
| rejection_reason | string | optional | Reason given at rejection |
| conversation_id | string | optional | Conversation that proposed it |
| message_id | string | optional | Message that proposed it |
| proposed_by | string | optional | Actor that proposed it |
| decided_by | string | optional | Actor that approved or rejected it |
| proposed_at | string | ✅ | Proposal timestamp (ISO 8601) |
| decided_at | string | optional | Decision timestamp (ISO 8601) |
AiPendingActionStatus
Allowed Values
pendingapprovedexecutedfailedrejected
AiStreamChunk
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| type | string | ✅ | Frame type (text-delta, tool-input-available, finish, error, …) |
ApproveAiPendingActionResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| status | Enum<'executed' | 'failed'> | ✅ | Outcome of executing the approved action |
| result | any | optional | Tool result, when executed |
| error | string | optional | Failure reason, when failed |
AutomationActionsResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| actions | { type: string; version: string; name: string; description?: string; … }[] | ✅ | Registered action descriptors (built-in + plugin) |
| total | integer | ✅ | Number of descriptors returned (after any filters) |
AutomationTriggerRequest
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| trigger | string | ✅ | |
| payload | Record<string, any> | ✅ |
AutomationTriggerResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| success | boolean | ✅ | |
| jobId | string | optional | |
| result | any | optional |
BatchDataRequest
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| object | string | ✅ | Object name |
| request | { operation: Enum<'create' | 'update' | 'upsert' | 'delete'>; records: object[]; options?: object } | ✅ | Batch operation request |
BatchDataResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| success | boolean | ✅ | Operation success status |
| error | { code: Enum<'VALIDATION_ERROR' | 'INVALID_FIELD' | 'MISSING_REQUIRED_FIELD' | … +264 more>; message: string; category?: string; httpStatus?: integer; … } | optional | Error details if success is false |
| meta | { timestamp: string; duration?: number; requestId?: string; traceId?: string } | optional | Response metadata |
| operation | Enum<'create' | 'update' | 'upsert' | 'delete'> | optional | Operation type that was performed |
| total | number | ✅ | Total number of records in the batch |
| succeeded | number | ✅ | Number of records that succeeded |
| failed | number | ✅ | Number of records that failed |
| results | { id?: string; success: boolean; errors?: object[]; data?: Record<string, any>; … }[] | ✅ | Detailed results for each record |
CheckPermissionRequest
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| object | string | ✅ | Object name to check permissions for |
| action | Enum<'create' | 'read' | 'edit' | 'delete' | 'transfer' | 'restore' | 'purge'> | ✅ | Action to check |
| recordId | string | optional | Specific record ID (for record-level checks) |
| field | string | optional | Specific field name (for field-level checks) |
CheckPermissionResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| allowed | boolean | ✅ | Whether the action is permitted |
| reason | string | optional | Reason if denied |
CreateAiConversationRequest
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| title | string | optional | Initial title |
| agentId | string | optional | Agent to bind the conversation to |
| metadata | Record<string, any> | optional | Conversation metadata |
CreateDataRequest
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| object | string | ✅ | The object name. |
| data | Record<string, any> | ✅ | The dictionary of field values to insert. |
CreateDataResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| object | string | ✅ | The object name. |
| id | string | ✅ | The ID of the newly created record. |
| record | Record<string, any> | ✅ | The created record, including server-generated fields (created_at, owner). |
| droppedFields | { object: string; fields: string[]; reason: Enum<'readonly' | 'readonly_when' | 'primary_key'> }[] | optional | Write-observability (#3407/#3431): caller-supplied fields that were LEGALLY stripped before the record was written — a non-system create cannot seed a static readonly column (#3043 ingress strip), so those keys are dropped and the field re-derives its default. Present ONLY when ≥1 field was dropped; the create still succeeded without them (status/success semantics unchanged). REST additionally surfaces this as the X-ObjectStack-Dropped-Fields response header. Optional — omit-when-empty keeps the shape backward-compatible for existing clients. |
CreateManyDataRequest
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| object | string | ✅ | Object name |
| records | Record<string, any>[] | ✅ | Array of records to create |
CreateManyDataResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| object | string | ✅ | Object name |
| records | Record<string, any>[] | ✅ | Created records |
| count | number | ✅ | Number of records created |
| droppedFields | { object: string; fields: string[]; reason: Enum<'readonly' | 'readonly_when' | 'primary_key'> }[] | optional | Write-observability (#3407/#3431/#3455): caller-supplied readonly fields the #3043 create-ingress strip removed before the rows were written. AGGREGATED across the batch (one event per object/reason with the union of dropped field names) rather than per-row, because the insert-time strip is static-readonly only — schema-uniform, so every row drops the same set. Present ONLY when ≥1 field was dropped; the creates still succeeded without them (count/success unchanged). Optional — omit-when-empty keeps the shape backward-compatible. (The per-row insertMany/batch paths carry per-row droppedFields on each result instead — see BatchOperationResultSchema.) |
DeleteDataRequest
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| object | string | ✅ | Object name |
| id | string | ✅ | Record ID to delete |
| expectedVersion | string | optional | Optimistic concurrency token (typically the updated_at value the client read). When provided, the server compares it against the current record version and returns 409 CONCURRENT_UPDATE if they differ. Optional — omit to skip the check. |
DeleteDataResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| object | string | ✅ | Object name |
| id | string | ✅ | Deleted record ID |
| success | boolean | ✅ | Whether deletion succeeded |
DeleteManyDataRequest
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| ids | string[] | ✅ | Array of record IDs to delete (server caps the count — see batch.maxBatchSize) |
| options | { atomic: boolean; returnRecords: boolean; continueOnError: boolean } | optional | Delete options |
| object | string | ✅ | Object name |
DeleteManyDataResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| success | boolean | ✅ | Operation success status |
| error | { code: Enum<'VALIDATION_ERROR' | 'INVALID_FIELD' | 'MISSING_REQUIRED_FIELD' | … +264 more>; message: string; category?: string; httpStatus?: integer; … } | optional | Error details if success is false |
| meta | { timestamp: string; duration?: number; requestId?: string; traceId?: string } | optional | Response metadata |
| operation | Enum<'create' | 'update' | 'upsert' | 'delete'> | optional | Operation type that was performed |
| total | number | ✅ | Total number of records in the batch |
| succeeded | number | ✅ | Number of records that succeeded |
| failed | number | ✅ | Number of records that failed |
| results | { id?: string; success: boolean; errors?: object[]; data?: Record<string, any>; … }[] | ✅ | Detailed results for each record |
DeleteMetaItemRequest
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| type | string | ✅ | Metadata type name |
| name | string | ✅ | Item name |
DeleteMetaItemResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| success | boolean | ✅ | |
| reset | boolean | optional | |
| message | string | optional |
DisablePackageRequest
Disable package request
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| id | string | ✅ | Package ID to disable |
DisablePackageResponse
Disable package response
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| package | { manifest: object; status?: Enum<'installed' | 'disabled' | 'installing' | 'upgrading' | 'uninstalling' | 'error'>; enabled?: boolean; installedAt?: string; … } | ✅ | Disabled package details |
| message | string | optional | Disable status message |
EnablePackageRequest
Enable package request
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| id | string | ✅ | Package ID to enable |
EnablePackageResponse
Enable package response
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| package | { manifest: object; status?: Enum<'installed' | 'disabled' | 'installing' | 'upgrading' | 'uninstalling' | 'error'>; enabled?: boolean; installedAt?: string; … } | ✅ | Enabled package details |
| message | string | optional | Enable status message |
FindDataRequest
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| object | string | ✅ | The unique machine name of the object to query (e.g. "account"). |
| query | { object: string; fields?: string[]; where?: any; search?: string | object; … } | optional | Structured query definition (filter, sort, select, pagination). |
FindDataResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| object | string | ✅ | The object name for the returned records. |
| records | Record<string, any>[] | ✅ | The list of matching records. |
| total | number | optional | Total number of records matching the filter (if requested). |
| nextCursor | string | optional | Cursor for the next page of results (cursor-based pagination). |
| hasMore | boolean | optional | True if there are more records available (pagination). |
GetDataRequest
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| object | string | ✅ | The object name. |
| id | string | ✅ | The unique record identifier (primary key). |
| select | string[] | optional | Fields to include in the response (allowlisted query param). |
| expand | string[] | optional | Lookup/master_detail field names to expand. The engine resolves these via batch $in queries, replacing foreign key IDs with full objects. |
GetDataResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| object | string | ✅ | The object name. |
| id | string | ✅ | The record ID. |
| record | Record<string, any> | ✅ | The complete record data. |
GetDiscoveryRequest
Properties
| Property | Type | Required | Description |
|---|
GetDiscoveryResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| name | string | optional | |
| version | string | ✅ | |
| environment | Enum<'production' | 'sandbox' | 'development'> | optional | Deployment posture a discovery response advertises. Deliberately three coarse buckets — a client reads this to answer "am I talking to production?", not to identify a specific environment (that is sys_environment / EnvironmentTypeSchema, a richer 7-member taxonomy). |
| routes | { data: string; metadata: string; discovery?: string; ui?: string; … } | optional | |
| locale | { default: string; supported: string[]; timezone: string } | optional | |
| services | Record<string, { enabled: boolean; status: Enum<'available' | 'registered' | 'unavailable' | 'degraded' | 'stub'>; handlerReady?: boolean; route?: string; … }> | optional | Per-service availability map keyed by CoreServiceName |
| capabilities | { comments: object; automation: object; cron: object; search: object; … } | optional | Hierarchical capability descriptors — the full WellKnownCapabilities vocabulary, every key present |
| schemaDiscovery | { openapi?: string; jsonSchema?: string } | optional | Schema discovery endpoints for API toolchain integration |
| scoping | { enabled: boolean; resolution: Enum<'required' | 'optional' | 'auto'>; scoped: boolean; environmentId?: string } | optional | Environment-scoping posture, added by the REST discovery endpoint |
| metadata | Record<string, any> | optional | Custom metadata key-value pairs for extensibility |
| apiName | string | optional | API name (deprecated — use name; removed in protocol 18) |
GetEffectivePermissionsRequest
Properties
| Property | Type | Required | Description |
|---|
GetEffectivePermissionsResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| objects | Record<string, { allowCreate: boolean; allowRead: boolean; allowEdit: boolean; allowDelete: boolean; … }> | ✅ | Effective object permissions keyed by object name |
| systemPermissions | string[] | ✅ | Effective system-level permissions |
GetFieldLabelsRequest
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| object | string | ✅ | Object name |
| locale | string | ✅ | BCP-47 locale code |
GetFieldLabelsResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| object | string | ✅ | Object name |
| locale | string | ✅ | Locale code |
| labels | Record<string, { label: string; help?: string; options?: Record<string, string> }> | ✅ | Field labels keyed by field name |
GetLocalesRequest
Properties
| Property | Type | Required | Description |
|---|
GetLocalesResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| locales | { code: string; label: string; isDefault: boolean }[] | ✅ | Available locales |
GetMetaItemCachedRequest
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| type | string | ✅ | Metadata type name |
| name | string | ✅ | Item name |
| cacheRequest | { ifNoneMatch?: string; ifModifiedSince?: string; cacheControl?: object } | optional | Cache validation parameters |
| locale | string | optional | Resolved response locale. Folded into the ETag so a language switch never returns a stale-locale 304 — metadata is translated after the cache validator check (issue #1319). |
GetMetaItemCachedResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| data | any | optional | Metadata payload (omitted for 304 Not Modified) |
| etag | { value: string; weak: boolean } | optional | ETag for this resource version |
| lastModified | string | optional | Last modification timestamp |
| cacheControl | { directives: Enum<'public' | 'private' | 'no-cache' | 'no-store' | 'must-revalidate' | 'max-age'>[]; maxAge?: number; staleWhileRevalidate?: number; staleIfError?: number } | optional | Cache control directives |
| notModified | boolean | ✅ | True if resource has not been modified (304 response) |
| version | string | optional | Metadata version identifier |
GetMetaItemLayeredResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| type | string | ✅ | Metadata type name (canonical singular) |
| name | string | ✅ | Item name |
| code | any | ✅ | LAYER 1 — the packaged artifact baseline exactly as shipped, before any tenant customization. null when no artifact ships this item (it exists only as an overlay). |
| overlay | any | ✅ | LAYER 2 — the stored customization row ALONE, not merged with code. null when this tenant has not customized the item. |
| overlayScope | Enum<'org' | 'env'> | null | ✅ | Which scope the overlay row was read from — org for a tenant overlay, env for an environment-level one. null exactly when overlay is null. |
| effective | any | ✅ | LAYER 3 — the merged result, i.e. the value an ordinary GET /meta/:type/:name would return under item. null when the item resolves to nothing at all. |
| _diagnostics | { valid: boolean; errors?: object[]; warnings?: object[] } | optional | Load-time spec-validation verdict for effective, so the Studio edit page can raise invalid-metadata banners and inline field errors without a second round trip. ABSENT for metadata types that register no Zod schema (function / service / router) — absence means "no opinion", never "valid". |
| lock | Enum<'none' | 'no-overlay' | 'no-delete' | 'full'> | ✅ | Resolved lock verdict (ADR-0010 §3.3), artifact winning over overlay. Always present on this path. |
| lockReason | string | optional | Human-readable explanation shown next to a refused write. Present only when the resolved item declares _lockReason. |
| lockSource | Enum<'artifact' | 'package' | 'env-forced'> | optional | Which layer asserted the lock. Present only when the resolved item declares _lockSource. |
| lockDocsUrl | string | optional | Documentation link surfaced beside lockReason. Present only when the resolved item declares _lockDocsUrl. |
| provenance | Enum<'package' | 'org' | 'env-forced'> | optional | Where the item came from (package | org | env-forced). Present only when the resolved item declares _provenance. |
| packageId | string | optional | Owning package machine id. Present only when the resolved item declares _packageId. |
| packageVersion | string | optional | Owning package version. Present only when the resolved item declares _packageVersion. |
| editable | boolean | ✅ | Whether an overlay write is permitted. Always present on this path. |
| deletable | boolean | ✅ | Whether deleting the overlay is permitted. Always present on this path. |
| resettable | boolean | ✅ | Whether the item can be reset to its packaged default. Always present on this path. |
GetMetaItemRequest
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| type | string | ✅ | Metadata type name |
| name | string | ✅ | Item name (snake_case identifier) |
| packageId | string | optional | Optional package ID to filter items by |
GetMetaItemResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| type | string | ✅ | Metadata type name |
| name | string | ✅ | Item name |
| item | any | ✅ | Metadata item definition |
| lock | Enum<'none' | 'no-overlay' | 'no-delete' | 'full'> | optional | Resolved lock verdict for this item (ADR-0010 §3.3). none means unlocked; no-overlay / no-delete / full refuse the corresponding write with 403 ITEM_LOCKED. Resolved from the document's _lock, with the packaged artifact winning over any org overlay. |
| lockReason | string | optional | Human-readable explanation shown next to a refused write. Present only when the resolved item declares _lockReason. |
| lockSource | Enum<'artifact' | 'package' | 'env-forced'> | optional | Which layer asserted the lock. Present only when the resolved item declares _lockSource. |
| lockDocsUrl | string | optional | Documentation link surfaced beside lockReason. Present only when the resolved item declares _lockDocsUrl. |
| provenance | Enum<'package' | 'org' | 'env-forced'> | optional | Where the item came from (package | org | env-forced). Present only when the resolved item declares _provenance. |
| packageId | string | optional | Owning package machine id. Present only when the resolved item declares _packageId. |
| packageVersion | string | optional | Owning package version. Present only when the resolved item declares _packageVersion. |
| editable | boolean | optional | Whether an overlay write is permitted — false iff lock is no-overlay or full. A derived verdict: do not recompute it from lock client-side. |
| deletable | boolean | optional | Whether deleting the overlay is permitted — false iff lock is no-delete or full. |
| resettable | boolean | optional | Whether the item can be reset to its packaged default — true iff it is artifact-backed, i.e. there is a baseline to reset TO. |
GetMetaItemsRequest
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| type | string | ✅ | Metadata type name (e.g., "object", "plugin") |
| packageId | string | optional | Optional package ID to filter items by |
GetMetaItemsResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| type | string | ✅ | Metadata type name |
| items | any[] | ✅ | Array of metadata items |
GetMetaTypesRequest
Properties
| Property | Type | Required | Description |
|---|
GetMetaTypesResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| types | string[] | ✅ | Available metadata type names (e.g., "object", "plugin", "view") |
| entries | { type: string; label: string; description?: string; filePatterns: string[]; … }[] | optional | Enriched per-type registry entries (Phase 3a) |
GetNotificationPreferencesRequest
Properties
| Property | Type | Required | Description |
|---|
GetNotificationPreferencesResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| preferences | { email: boolean; push: boolean; inApp: boolean; digest: Enum<'none' | 'daily' | 'weekly'>; … } | ✅ | Current notification preferences |
GetObjectPermissionsRequest
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| object | string | ✅ | Object name to get permissions for |
GetObjectPermissionsResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| object | string | ✅ | Object name |
| permissions | { allowCreate: boolean; allowRead: boolean; allowEdit: boolean; allowDelete: boolean; … } | ✅ | Object-level permissions |
| fieldPermissions | Record<string, { readable: boolean; editable: boolean }> | optional | Field-level permissions keyed by field name |
GetPackageRequest
Get package request
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| id | string | ✅ | Package identifier |
GetPackageResponse
Get package response
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| package | { manifest: object; status?: Enum<'installed' | 'disabled' | 'installing' | 'upgrading' | 'uninstalling' | 'error'>; enabled?: boolean; installedAt?: string; … } | ✅ | Package details |
GetPresenceRequest
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| channel | string | ✅ | Channel to get presence for |
GetPresenceResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| channel | string | ✅ | Channel name |
| members | { userId: string; status: Enum<'online' | 'away' | 'busy' | 'offline'>; lastSeen: string; metadata?: Record<string, any> }[] | ✅ | Active members and their presence state |
GetTranslationsRequest
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| locale | string | ✅ | BCP-47 locale code |
GetTranslationsResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| locale | string | ✅ | Locale code |
| translations | { objects?: Record<string, object>; apps?: Record<string, object>; messages?: Record<string, string>; globalActions?: Record<string, object>; … } | ✅ | Translation data |
GetUiViewRequest
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| object | string | ✅ | Object name (snake_case) |
| type | Enum<'list' | 'form'> | ✅ | View type |
GetUiViewResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| name | string | optional | Item name — supplied by the metadata door; for an object-scoped container it is the object name. |
| label | string | Record<string, string> | optional | Human-readable label shown in metadata lists. |
| object | string | optional | Object this container binds to — how a stack-level views: [...] entry says which object its views belong to; read by getViewsByObject() / GET /meta/view?object=. |
| list | { name?: string; label?: string | Record<string, string>; type?: Enum<'grid' | 'kanban' | 'gallery' | 'calendar' | 'timeline' | 'gantt' | 'map' | 'chart' | 'tree'>; data?: object | … +3 more; … } | optional | |
| form | { type?: Enum<'simple' | 'tabbed' | 'wizard' | 'split' | 'drawer' | 'modal'>; layout?: Enum<'vertical' | 'horizontal' | 'inline' | 'grid'>; columns?: integer; title?: string; … } | optional | |
| listViews | Record<string, { name?: string; label?: string | Record<string, string>; type?: Enum<'grid' | 'kanban' | 'gallery' | 'calendar' | 'timeline' | 'gantt' | 'map' | 'chart' | 'tree'>; data?: object | … +3 more; … }> | optional | Additional named list views (views mode — dropdown userFilters allowed, no tabs; ADR-0047) |
| formViews | Record<string, { type?: Enum<'simple' | 'tabbed' | 'wizard' | 'split' | 'drawer' | 'modal'>; layout?: Enum<'vertical' | 'horizontal' | 'inline' | 'grid'>; columns?: integer; title?: string; … }> | optional | Additional named form views |
| protection | { lock: Enum<'none' | 'no-overlay' | 'no-delete' | 'full'>; reason: string; docsUrl?: string } | optional | Package author protection block — lock policy for this view. |
| _lock | Enum<'none' | 'no-overlay' | 'no-delete' | 'full'> | optional | Item-level lock — controls overlay & delete (ADR-0010). |
| _lockReason | string | optional | Human-readable reason shown when a write is refused by _lock. |
| _lockSource | Enum<'artifact' | 'package' | 'env-forced'> | optional | Layer that set _lock (artifact | package | env-forced). |
| _provenance | Enum<'package' | 'org' | 'env-forced'> | optional | Origin of the item (package | org | env-forced). |
| _packageId | string | optional | Owning package machine id. |
| _packageVersion | string | optional | Owning package version. |
| _lockDocsUrl | string | optional | Optional documentation link surfaced next to _lockReason. |
HttpFindQueryParams
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| filter | string | optional | JSON-encoded filter expression (canonical, singular). |
| filters | string | optional | JSON-encoded filter expression (deprecated plural alias). |
| select | string | optional | Comma-separated list of fields to retrieve. |
| sort | string | optional | Sort expression (e.g. "name asc,created_at desc" or "-created_at"). |
| orderBy | string | optional | Alias for sort (OData compatibility). |
| top | number | optional | Max records to return (limit). |
| skip | number | optional | Records to skip (offset). |
| expand | string | optional | Comma-separated list of lookup/master_detail field names to expand. Resolved to populate array and passed to the engine for batch $in expansion. |
| search | string | optional | Full-text search query. |
| distinct | never | optional | [REMOVED] query.distinct was removed in @objectstack/spec 17 (#4286, ADR-0049 / ADR-0078) — no driver ever rendered SELECT DISTINCT; the flag's only observable effect was MIS-WIRED: the REST list path treated a distinct query as not countable and silently degraded total/hasMore to a page-local estimate while still returning duplicate rows. Delete the key; QueryBuilder.distinct() was removed with it, and the count suppression is gone (total is truthful again). For unique values of one column use the SQL/memory drivers' distinct(object, field) door; for unique combinations, groupBy; for a deduplicated count, the count_distinct aggregation. |
| count | boolean | optional | Include total count in response. |
InstallPackageRequest
Install package request
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| manifest | { id: string; namespace?: string; defaultDatasource?: string; version: string; … } | ✅ | Package manifest to install |
| settings | Record<string, any> | optional | User-provided settings at install time |
| enableOnInstall | boolean | optional | Whether to enable immediately after install |
| platformVersion | string | optional | Current platform version for compatibility verification |
InstallPackageResponse
Install package response
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| package | { manifest: object; status?: Enum<'installed' | 'disabled' | 'installing' | 'upgrading' | 'uninstalling' | 'error'>; enabled?: boolean; installedAt?: string; … } | ✅ | Installed package details |
| message | string | optional | Installation status message |
| dependencyResolution | { dependencies: object[]; canProceed: boolean; requiredActions: object[]; installOrder: string[]; … } | optional | Dependency resolution result from install analysis |
ListAiConversationsRequest
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| agentId | string | optional | Filter by agent |
| limit | integer | optional | Maximum conversations to return |
| cursor | string | optional | Pagination cursor |
ListAiConversationsResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| conversations | { id: string; title?: string; agentId?: string; userId?: string; … }[] | ✅ | Matching conversations |
ListAiPendingActionsRequest
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| status | Enum<'pending' | 'approved' | 'executed' | 'failed' | 'rejected'> | optional | Filter by status |
| conversationId | string | optional | Filter by proposing conversation |
| limit | integer | optional | Max rows (server default 100) |
ListAiPendingActionsResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| items | { id: string; object_name: string; action_name: string; tool_name: string; … }[] | ✅ | Queued actions, newest first |
| total | number | ✅ | Number of rows returned (not a total across pages) |
ListNotificationsRequest
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| read | boolean | optional | Filter by read status |
| type | string | optional | Filter by notification type |
| limit | number | optional | Maximum number of notifications to return — the newest N. Omitted leaves the window to the server, which is not a fixed part of this contract: the platform inbox answers 50 and clamps any requested value into 1..200 rather than refusing it. This endpoint is not paginated — there is no continuation token, so a larger window is the only way to see more. |
| cursor | never | optional | [REMOVED] cursor was removed from GET /api/v1/notifications in @objectstack/spec 17 (#6361, ADR-0049) — it was declared on the request AND the response and honoured on neither: the server reads only read/type/limit, and no emit site ever wrote the response key, so a caller paginating by it re-read the first window forever with no error and no 400. Delete the key; the cursor argument of client.notifications.list() was removed with it. This route is NOT paginated — it answers the newest limit notifications and stops, so ask for a bigger window (limit, clamped by the server into 1..200) instead of a next page. A first-class inbox cursor, if ever built, will be a response-minted opaque token, not this key. |
ListNotificationsResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| notifications | { id: string; type: string; title: string; body: string; … }[] | ✅ | List of notifications — the newest window, not a page |
| unreadCount | number | ✅ | Total number of unread notifications |
| cursor | never | optional | [REMOVED] cursor was removed from GET /api/v1/notifications in @objectstack/spec 17 (#6361, ADR-0049) — it was declared on the request AND the response and honoured on neither: the server reads only read/type/limit, and no emit site ever wrote the response key, so a caller paginating by it re-read the first window forever with no error and no 400. Delete the key; the cursor argument of client.notifications.list() was removed with it. This route is NOT paginated — it answers the newest limit notifications and stops, so ask for a bigger window (limit, clamped by the server into 1..200) instead of a next page. A first-class inbox cursor, if ever built, will be a response-minted opaque token, not this key. |
ListPackagesRequest
List packages request
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| status | Enum<'installed' | 'disabled' | 'installing' | 'upgrading' | 'uninstalling' | 'error'> | optional | Filter by package status |
| type | Enum<'plugin' | 'ui' | 'driver' | 'server' | 'app' | 'theme' | 'agent' | 'objectql' | 'module' | 'gateway' | 'adapter'> | optional | Filter by package type |
| enabled | boolean | optional | Filter by enabled state |
ListPackagesResponse
List packages response
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| packages | { manifest: object; status?: Enum<'installed' | 'disabled' | 'installing' | 'upgrading' | 'uninstalling' | 'error'>; enabled?: boolean; installedAt?: string; … }[] | ✅ | List of installed packages |
| total | number | ✅ | Total package count |
MarkAllNotificationsReadRequest
Properties
| Property | Type | Required | Description |
|---|
MarkAllNotificationsReadResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| success | boolean | ✅ | Whether the operation succeeded |
| readCount | number | ✅ | Number of notifications marked as read |
MarkNotificationsReadRequest
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| ids | string[] | ✅ | Notification IDs to mark as read |
MarkNotificationsReadResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| success | boolean | ✅ | Whether the operation succeeded |
| readCount | number | ✅ | Number of notifications marked as read |
Notification
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| id | string | ✅ | Notification ID |
| type | string | ✅ | Notification type |
| title | string | ✅ | Notification title |
| body | string | ✅ | Notification body text |
| read | boolean | ✅ | Whether notification has been read |
| data | Record<string, any> | optional | Additional notification data |
| actionUrl | string | optional | URL to navigate to when clicked |
| createdAt | string | ✅ | When notification was created |
NotificationPreferences
Properties
| Property | Type | Required | Description |
|---|---|---|---|
boolean | ✅ | Receive email notifications | |
| push | boolean | ✅ | Receive push notifications |
| inApp | boolean | ✅ | Receive in-app notifications |
| digest | Enum<'none' | 'daily' | 'weekly'> | ✅ | Email digest frequency |
| channels | Record<string, { enabled: boolean; email?: boolean; push?: boolean }> | optional | Per-channel notification preferences |
PublishMetaItemResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| success | boolean | ✅ | Always true on a 2xx — the draft was promoted. It does NOT cover the best-effort side effects below, each of which reports its own success. |
| version | string | ✅ | Content hash of the just-promoted body, and the token the ADR-0008 optimistic-concurrency chain runs on: send it back as the If-Match request header on the next write to that item and a concurrent edit is reported as 409 metadata_conflict instead of silently overwritten. Opaque to callers — echo it verbatim, never parse it. Currently emitted as sha256:<64 hex chars>, but the format is not part of this contract. |
| seq | integer | ✅ | Monotonic sequence number of the op='publish' metadata event this promotion appended to the item history (sys_metadata_history.event_seq). Orders writes; unlike version it is not an OCC token. |
| seedApplied | { success: boolean; inserted: integer; updated: integer; error?: string; … } | optional | Outcome of materializing a published seed body into data rows. Present ONLY when the published type is seed — publishing a seed is what makes its rows live, so the load rides along with the metadata promotion. Best-effort: a seed-load problem is surfaced here, never thrown, so a caller must check seedApplied.success instead of assuming the 200 covered the data. Absent on the batch path, which suppresses the per-item apply and loads every seed body in one later pass. |
| materializeApplied | { success: boolean; inserted: integer; updated: integer; error?: string } | optional | Outcome of the ADR-0086 P2 publish-time materializer — the step that projects the published body into its data-plane row (e.g. permission → sys_permission_set, under the owning package). Present ONLY when a materializer is registered for this metadata type, which is why it is optional: its absence means "no materializer ran", never "it failed". Best-effort, same contract as seedApplied. |
| projectionApplied | { success: boolean; error?: string } | optional | Outcome of the awaited ADR-0094 mutation projector — the post-persist step that materializes this metadata into its derived data-plane read model. The same receipt {@link SaveMetaItemResponseSchema} carries, because the projector runs on BOTH write doors: a direct active save and this draft→active promotion. Present ONLY when a projector is registered for this metadata type. Best-effort — a projector failure is reported here and logged, never thrown. |
| message | string | optional | Human-readable receipt, e.g. Published draft — type=view, name=cases [seq=3]. The producer sets it on every publish today; it stays optional to match the producer's own signature and its SaveMetaItemResponse twin, and because an absent human-readable string strips no data — the failure mode #5745 exists to prevent. |
RealtimeConnectRequest
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| transport | Enum<'websocket' | 'sse' | 'polling'> | optional | Preferred transport protocol |
| channels | string[] | optional | Channels to subscribe to on connect |
| token | string | optional | Authentication token |
RealtimeConnectResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| connectionId | string | ✅ | Unique connection identifier |
| transport | Enum<'websocket' | 'sse' | 'polling'> | ✅ | Negotiated transport protocol |
| url | string | optional | WebSocket/SSE endpoint URL |
RealtimeDisconnectRequest
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| connectionId | string | optional | Connection ID to disconnect |
RealtimeDisconnectResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| success | boolean | ✅ | Whether disconnection succeeded |
RealtimeSubscribeRequest
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| channel | string | ✅ | Channel name to subscribe to |
| events | string[] | optional | Specific event types to listen for |
| filter | Record<string, any> | optional | Event filter criteria |
RealtimeSubscribeResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| subscriptionId | string | ✅ | Unique subscription identifier |
| channel | string | ✅ | Subscribed channel name |
RealtimeUnsubscribeRequest
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| subscriptionId | string | ✅ | Subscription ID to cancel |
RealtimeUnsubscribeResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| success | boolean | ✅ | Whether unsubscription succeeded |
RegisterDeviceRequest
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| token | string | ✅ | Device push notification token |
| platform | Enum<'ios' | 'android' | 'web'> | ✅ | Device platform |
| deviceId | string | optional | Unique device identifier |
| name | string | optional | Device friendly name |
RegisterDeviceResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| deviceId | string | ✅ | Registered device ID |
| success | boolean | ✅ | Whether registration succeeded |
RejectAiPendingActionResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| status | 'rejected' | ✅ | Always "rejected" |
| id | string | ✅ | The rejected action id |
RuntimeAuthoringIssue
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| rule | string | ✅ | Stable diagnostic rule id (flow-multi-write-unfiltered, approval-expression-invalid, …). Machine-readable and stable across releases — the key a renderer groups or suppresses by. |
| path | string | ✅ | Config path inside the SUBMITTED body (flows[0].nodes[1].config.multi), so an editor can jump to the offending key. May be empty when the finding is about the item as a whole. |
| where | string | ✅ | Human-readable location — flow "leave_approval" · node "approve". Prose for a person; use path for anything mechanical. |
| message | string | ✅ | What is wrong, in the rule author's own words. |
| hint | string | ✅ | How to fix it. |
| severity | Enum<'error' | 'warning' | 'info'> | ✅ | How the gate treated this finding. error means the write was REFUSED (these appear on the 422, never on a 2xx); warning / info are advisory — the write succeeded and the finding is FYI. |
SaveMetaItemRequest
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| type | string | ✅ | Metadata type name |
| name | string | ✅ | Item name |
| item | any | ✅ | Metadata item definition |
SaveMetaItemResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| success | boolean | ✅ | |
| version | string | ✅ | Content hash of the just-committed body, and the token the ADR-0008 optimistic-concurrency chain runs on: send it back as the If-Match request header on the next write to that item and a concurrent edit is reported as 409 metadata_conflict instead of silently overwritten. Opaque to callers — echo it verbatim, never parse it. Currently emitted as sha256:<64 hex chars>, but the format is not part of this contract. |
| seq | integer | ✅ | Monotonic sequence number of the metadata event this write appended to the item history (sys_metadata_history.event_seq). Orders writes; unlike version it is not an OCC token. |
| state | Enum<'draft' | 'active'> | ✅ | Lifecycle the body was written into: "draft" when the request asked for draft mode (?mode=draft), otherwise "active" (published and live). A draft is staged only — it is not served to the runtime until published. |
| projectionApplied | { success: boolean; error?: string } | optional | Outcome of the awaited ADR-0094 mutation projector — the post-persist step that materializes this metadata into its derived data-plane read model (e.g. permission → sys_permission_set). Present ONLY when a projector is registered for this metadata type, which is why it is optional: its absence means "no projector ran", never "the projection failed". Best-effort by design — a projector failure is reported here and logged, never thrown, so a caller that needs the read model to be live must check projectionApplied.success rather than rely on the 200. |
| advisories | { rule: string; path: string; where: string; message: string; … }[] | optional | Non-gating findings from the #4463 runtime authoring gate — the same shared author-time rules os validate / os build / os lint run, applied to this body on its way to active. The write SUCCEEDED; these are what the gate has to say about it anyway (#4717, closing #4463 D3). Present ONLY when at least one advisory was raised — an empty array is never emitted, so a clean save's response bytes are unchanged and absence means "nothing to report", never "the gate did not run". Advisory by construction: every entry has severity warning or info, because an error finding refuses the write and arrives as the 422 invalid_metadata envelope instead of here. A caller that ignores this key behaves exactly as before. Runtime-only: the CLI surfaces the same findings on its own stdout, and a Studio / MCP / AI author has no CLI at all, which is the gap #4463 exists to close. NOTE the door asymmetry — POST /meta/:type/:name/publish does not carry this field yet (its declaration landed separately as #7294); the gate runs on both doors, only the save door reports. |
| message | string | optional |
SetPresenceRequest
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| channel | string | ✅ | Channel to set presence in |
| state | { userId: string; status: Enum<'online' | 'away' | 'busy' | 'offline'>; lastSeen: string; metadata?: Record<string, any> } | ✅ | Presence state to set |
SetPresenceResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| success | boolean | ✅ | Whether presence was set |
UninstallPackageRequest
Uninstall package request
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| id | string | ✅ | Package ID to uninstall |
UninstallPackageResponse
Uninstall package response
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| id | string | ✅ | Uninstalled package ID |
| success | boolean | ✅ | Whether uninstall succeeded |
| message | string | optional | Uninstall status message |
UnregisterDeviceRequest
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| deviceId | string | ✅ | Device ID to unregister |
UnregisterDeviceResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| success | boolean | ✅ | Whether unregistration succeeded |
UpdateAiConversationRequest
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| title | string | optional | New title |
| metadata | Record<string, any> | optional | New metadata |
UpdateDataRequest
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| object | string | ✅ | The object name. |
| id | string | ✅ | The ID of the record to update. |
| data | Record<string, any> | ✅ | The fields to update (partial update). |
| expectedVersion | string | optional | Optimistic concurrency token (typically the updated_at value the client read). When provided, the server compares it against the current record version and returns 409 CONCURRENT_UPDATE if they differ. Optional — omit to skip the check. |
UpdateDataResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| object | string | ✅ | Object name |
| id | string | ✅ | Updated record ID |
| record | Record<string, any> | ✅ | Updated record |
| droppedFields | { object: string; fields: string[]; reason: Enum<'readonly' | 'readonly_when' | 'primary_key'> }[] | optional | Write-observability (#3407/#3431): caller-supplied fields the engine LEGALLY stripped from the write before persisting — static readonly (#2948) or a TRUE readonlyWhen predicate (#3042). Present ONLY when ≥1 field was dropped; the update still succeeded without them (status/success semantics unchanged — stripping is legitimate, not an error). REST additionally surfaces this as the X-ObjectStack-Dropped-Fields response header. Optional — omit-when-empty keeps the shape backward-compatible for existing clients that only read record. |
UpdateManyDataRequest
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| records | { id: string; data: Record<string, any> }[] | ✅ | Array of records to update (server caps the count — see batch.maxBatchSize) |
| options | { atomic: boolean; returnRecords: boolean; continueOnError: boolean } | optional | Update options |
| object | string | ✅ | Object name |
UpdateManyDataResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| success | boolean | ✅ | Operation success status |
| error | { code: Enum<'VALIDATION_ERROR' | 'INVALID_FIELD' | 'MISSING_REQUIRED_FIELD' | … +264 more>; message: string; category?: string; httpStatus?: integer; … } | optional | Error details if success is false |
| meta | { timestamp: string; duration?: number; requestId?: string; traceId?: string } | optional | Response metadata |
| operation | Enum<'create' | 'update' | 'upsert' | 'delete'> | optional | Operation type that was performed |
| total | number | ✅ | Total number of records in the batch |
| succeeded | number | ✅ | Number of records that succeeded |
| failed | number | ✅ | Number of records that failed |
| results | { id?: string; success: boolean; errors?: object[]; data?: Record<string, any>; … }[] | ✅ | Detailed results for each record |
UpdateNotificationPreferencesRequest
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| preferences | { email?: boolean; push?: boolean; inApp?: boolean; digest?: Enum<'none' | 'daily' | 'weekly'>; … } | ✅ | Preferences to update |
UpdateNotificationPreferencesResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| preferences | { email: boolean; push: boolean; inApp: boolean; digest: Enum<'none' | 'daily' | 'weekly'>; … } | ✅ | Updated notification preferences |
ValidateDataIssue
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| field | string | ✅ | The field the finding is about (_record for an object-level rule). |
| code | string | ✅ | Machine-readable finding code, e.g. required, invalid_type, rule_violation. |
| message | string | ✅ | Human-readable message — a validation rule's author-written text where one exists. |
ValidateDataRequest
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| object | string | ✅ | The object name. |
| data | Record<string, any> | Record<string, any>[] | ✅ | A candidate record, or an array of them. Nothing is persisted. |
| mode | Enum<'insert' | 'update'> | optional | Which write the verdict should predict. insert (default) walks every declared field, so a missing required field is a finding; update judges only the supplied keys, matching a PATCH. |
ValidateDataResponse
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| object | string | ✅ | The object name. |
| mode | Enum<'insert' | 'update'> | ✅ | The write mode the verdict was reached for. |
| valid | boolean | ✅ | True when EVERY row is valid — the whole-set answer. |
| results | { valid: boolean; errors: object[]; warnings: object[] }[] | ✅ | Per-row verdicts, in submission order. |
| posture | { valueShapeStrict: boolean; mediaValueShapeStrict: boolean } | ✅ | The ADR-0104 posture the verdict was reached under — reported because it is the difference between "this row is fine" and "this row is fine HERE". The same row can be an error on a self-certified deployment and an admitted warning on an un-migrated one, and a caller explaining a verdict needs to know which it got. An unconditionally-strict preview was considered and rejected (#4633 option B): it would fail rows on every un-migrated deployment that the write would have accepted. |