Metadata API — read and publish packages
REST endpoints for object schemas, metadata types, UI views, and package management.
Manage object schemas, metadata types, UI views, and installed packages over REST. All paths are relative to the base URL (defaults to /api/v1) — see the API Overview for discovery and service availability.
Metadata
Retrieve and manage object schemas, metadata types, and UI views. Always available — provided by the kernel.
A type segment these routes cannot recognise, but which reaches for a metadata type the
platform declares, is refused 400 INVALID_REQUEST rather than served — see
unrecognised type spelling
in the error catalog for the envelope and the correction it names.
GET /meta
List all registered metadata types.
Response: { types: ["object", "view", "plugin", ...] }
GET /meta/:type
List all items of a metadata type.
| Parameter | Location | Description |
|---|---|---|
type | path | Metadata type name — the singular spelling (object, view, flow) |
Metadata type names are singular (Prime Directive #3) and this segment is the
type name itself, so the spelling to send is object — never objects. The
plurals elsewhere in this API name something else: a collection of records
(/data/:object) or a package-manifest key (objects: [...]). Neither carries
across to a /meta type segment.
Listing applies the ADR-0046 §6.7 audience gate to books and docs, RBAC filtering to privileged apps, and the usual response shaping.
Response: { type: "object", items: [{ name: "account", ... }, ...] }
GET /meta/:type/:name
Get a specific metadata item with optional ETag caching.
| Parameter | Location | Description |
|---|---|---|
type | path | Metadata type name |
name | path | Item name (snake_case) |
If-None-Match | header | ETag 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.
Saving requires the manage_metadata capability. Under a group or isolated
tenancy posture it also requires the platform operator, for every type: the
environment's metadata is shared by every organization (ADR-0131 D12 items 7–8,
D11), so a manage_metadata holder inside one organization is refused
403 FORBIDDEN naming the posture. The same holds for DELETE (reset),
POST /meta/:type/:name/publish and POST /meta/:type/:name/rollback, and for
POST /meta/_migrate-stored, the install-wide rewrite of the stored metadata,
preview included.
Creates are gated per type: MetadataTypeRegistryEntry.allowRuntimeCreate decides
whether a brand-new name may be minted under that type at all, separately from
whether an item that already exists may be overlaid (allowEnvironmentOverlay). A type that
declines the create half still accepts updates to names that already exist, and its
refusal — 403 NOT_CREATABLE — names the route that does work. The flags are
documented on
MetadataTypeRegistryEntry;
which types currently decline which half is tracked in the
overlay whitelist
rather than enumerated on this page, so this caveat doesn't go stale the next time a
type is retired.
This verb also refuses a :type segment that is not a metadata type the platform
declares at all — not a recognised spelling, and not a misspelling of one either —
with 400 INVALID_REQUEST, before any namespace is minted for it. The refusal is
scoped to this verb: GET and DELETE on an item that already exists are
unaffected. See unrecognised type spelling
in the error catalog for the envelope — the same code and status cover both this
refusal and the misspelling one above; the message text tells them apart.
Body: { type: "object", name: "account", item: { ... } }
Response: { success: true }
GET /ui/view/:object/:type
Get an auto-generated UI view for an object.
| Parameter | Location | Description |
|---|---|---|
object | path | Object name (snake_case) |
type | path | list or form |
Response: Full ViewSchema definition with columns/fields derived from the object schema.
Package Management
Manage installed plugins/packages.
GET /packages
List installed packages.
POST /packages
Install a package from its manifest (SDK: client.packages.install). Re-installing an
already-installed id returns 409 Conflict unless overwrite: true.
Body: { manifest: { id: "com.objectstack.plugin-auth", name: "Plugin Auth", version: "1.0.0", ... }, settings?: { ... }, enableOnInstall?: true, overwrite?: false }
Response: { package: { id: "com.objectstack.plugin-auth", version: "1.0.0", ... }, message?: "..." }
POST /packages/publish
Publish a package (manifest + metadata) to the package marketplace registry. This is publisher tooling, not part of the app SDK surface.
Body: { manifest: { id: "com.objectstack.plugin-auth", name: "Plugin Auth", version: "1.0.0", ... }, metadata: { objects: [...], views: [...], ... } }
Response: { success: true, message: "...", package: { id: "com.objectstack.plugin-auth", version: "1.0.0" } }
GET /packages/:id
Get package details.
DELETE /packages/:id
Uninstall a package.
Under a group or isolated tenancy posture every /packages write is the
platform operator's (ADR-0131 D12 items 7–8, D11): install (POST /packages),
the manifest PATCH, enable, disable, publish, publish-drafts,
discard-drafts, revert, rollback, commits/:commitId/revert, duplicate,
adopt-orphans and this delete. Any other caller, a manage_metadata holder
inside one organization included, is refused 403 PERMISSION_DENIED naming the
posture, before anything is read or written, whatever the package carries.
Reads are unchanged. Under single every manage_metadata holder writes as
before.
PATCH /packages/:id/enable
Enable a disabled package.
PATCH /packages/:id/disable
Disable a package without uninstalling.
See also
- API Overview — discovery, error handling, and protocol types
- Data API — CRUD, batch operations, and analytics