RootCX
Docs
Pricing
RootCX/RootCX
Introduction
What is RootCX?How it Works
Build
Getting StartedApplicationAI AgentIntegrationDeploying
Platform
CoreAuthenticationRBACData APISecret VaultJob QueueAudit LogReal-time Logs
Developers
QuickstartReact SDKBackend & RPCManifest ReferenceREST APISelf-Hosting
RootCXDevelopersManifests

Manifest Reference

The manifest.json is the single source of truth for your application. It declares your entities, fields, permissions, and actions. Everything else — tables, CRUD API, constraints — is derived from it automatically.

Top-level fields

Field Type Required Default Description
appId string Yes Unique identifier. Becomes the PostgreSQL schema name. Immutable after first deploy.
name string Yes Display name shown in the Studio.
type string No "app" Application type: "app" (default) or "integration".
version string No "0.0.1" Semantic version for deployment history.
description string No "" Short description shown in the Studio.
dataContract array No [] Array of entity definitions.
permissions object No Object with a permissions array of permission keys.
actions array No [] Array of RPC action declarations.
configSchema object No JSON Schema for the app's configuration structure.
webhooks string[] No [] Webhook event names the app can receive.
instructions string No Usage instructions for AI agents interacting with this app.
appId must be lowercase snake_case (letters, digits, underscores). Hyphens are not allowed. It is immutable after first deploy and becomes the PostgreSQL schema name directly (e.g. appId: "crm" creates schema crm).

dataContract[]

Each entry becomes a PostgreSQL table. System columns (id, created_at, updated_at) are added automatically. You can override id with a custom primary key, but created_at and updated_at are always managed by the system and cannot be overridden.

Field Type Required Description
entityName string Yes Table name. Used in API routes (/api/v1/apps/{appId}/collections/{entityName}).
fields array Yes Array of field definitions.
"dataContract": [
  {
    "entityName": "contacts",
    "fields": [
      { "name": "first_name", "type": "text", "required": true },
      { "name": "last_name",  "type": "text", "required": true },
      { "name": "email",      "type": "text" },
      { "name": "phone",      "type": "text" }
    ]
  }
]

dataContract[].fields[]

Field Type Required Default Description
name string Yes Column name. created_at and updated_at are reserved (system-managed). You may declare a custom id field to override the default UUID primary key.
type string Yes One of the field types.
required boolean No false Adds a NOT NULL constraint.
defaultValue any No Default on insert. Accepts JSON values: "draft", 0, false, {"key": "val"}.
enumValues string[] No Allowed values. Generates a CHECK constraint.
references object No For entity_link only. { "entity": "...", "field": "id" }. Generates a FOREIGN KEY.
isPrimaryKey boolean No false Custom primary key. Rarely needed.

Field types

Fields map directly to PostgreSQL types:

Type PostgreSQL Description
text TEXT Variable-length string.
number DOUBLE PRECISION 64-bit floating-point.
boolean BOOLEAN True/false.
date DATE Calendar date (YYYY-MM-DD).
timestamp TIMESTAMPTZ Date and time in UTC.
json JSONB Arbitrary JSON. Supports GIN indexing.
file TEXT File reference from the upload endpoint.
entity_link UUID REFERENCES Foreign key. Requires references.
[text] TEXT[] Array of strings.
[number] DOUBLE PRECISION[] Array of numbers.

Relationships and constraints

Use entity_link to create foreign keys between entities, enumValues to restrict allowed values, and required to enforce NOT NULL:

{
  "name": "stage",
  "type": "text",
  "enumValues": ["lead", "qualified", "proposal", "won", "lost"],
  "defaultValue": "lead"
},
{
  "name": "contact_id",
  "type": "entity_link",
  "references": { "entity": "contacts", "field": "id" }
},
{
  "name": "company_id",
  "type": "entity_link",
  "references": { "entity": "companies", "field": "id" }
}

actions[]

Actions are RPC methods declared in the manifest. Declaring them makes them discoverable by the Studio, integrations, and AI agents.

Field Type Required Description
id string Yes Must match a key in serve().
name string Yes Display name for Studio and AI agents.
description string No What the action does.
inputSchema object No JSON Schema for input parameters.
outputSchema object No JSON Schema for the return value.

To gate access, declare a matching key in the permissions block (e.g. action.pipeline).

"actions": [
  {
    "id": "pipeline",
    "name": "Pipeline Summary",
    "description": "Returns deal counts per stage",
    "outputSchema": {
      "type": "object",
      "properties": {
        "lead": { "type": "number" },
        "qualified": { "type": "number" },
        "proposal": { "type": "number" },
        "won": { "type": "number" },
        "lost": { "type": "number" }
      }
    }
  }
]

permissions

Add permission keys to control access. Keys follow the entity.action convention. Assign them to roles via the Studio Roles & Permissions panel or the RBAC API.

"permissions": {
  "permissions": [
    { "key": "contacts.create", "description": "Create contacts" },
    { "key": "contacts.read",   "description": "View contacts" },
    { "key": "contacts.update", "description": "Edit contacts" },
    { "key": "contacts.delete", "description": "Delete contacts" },
    { "key": "deals.update",    "description": "Edit deals" },
    { "key": "deals.delete",    "description": "Delete deals" }
  ]
}

configSchema

An optional JSON Schema that defines the structure of app-level configuration. Useful for settings that vary per deployment (feature flags, thresholds, display preferences):

"configSchema": {
  "type": "object",
  "properties": {
    "defaultCurrency": { "type": "string", "default": "USD" },
    "enableNotifications": { "type": "boolean", "default": true }
  }
}

Full example manifest

{
  "appId": "sales_crm",
  "name": "Sales CRM",
  "version": "1.0.0",
  "description": "Manage contacts, companies, and deals with a sales pipeline.",
  "dataContract": [
    {
      "entityName": "contacts",
      "fields": [
        { "name": "first_name", "type": "text", "required": true },
        { "name": "last_name",  "type": "text", "required": true },
        { "name": "email",      "type": "text" },
        { "name": "phone",      "type": "text" },
        { "name": "company_id", "type": "entity_link", "references": { "entity": "companies", "field": "id" } }
      ]
    },
    {
      "entityName": "companies",
      "fields": [
        { "name": "name",     "type": "text", "required": true },
        { "name": "industry", "type": "text" },
        { "name": "website",  "type": "text" }
      ]
    },
    {
      "entityName": "deals",
      "fields": [
        { "name": "title",      "type": "text", "required": true },
        { "name": "value",      "type": "number" },
        { "name": "stage",      "type": "text", "enumValues": ["lead", "qualified", "proposal", "won", "lost"], "defaultValue": "lead" },
        { "name": "contact_id", "type": "entity_link", "references": { "entity": "contacts", "field": "id" } },
        { "name": "company_id", "type": "entity_link", "references": { "entity": "companies", "field": "id" } },
        { "name": "notes",      "type": "json" }
      ]
    }
  ],
  "actions": [
    {
      "id": "pipeline",
      "name": "Pipeline Summary",
      "description": "Returns deal counts per stage",
      "outputSchema": {
        "type": "object",
        "properties": {
          "lead": { "type": "number" },
          "qualified": { "type": "number" },
          "proposal": { "type": "number" },
          "won": { "type": "number" },
          "lost": { "type": "number" }
        }
      }
    }
  ],
  "permissions": {
    "permissions": [
      { "key": "contacts.create", "description": "Create contacts" },
      { "key": "contacts.read",   "description": "View contacts" },
      { "key": "contacts.update", "description": "Edit contacts" },
      { "key": "contacts.delete", "description": "Delete contacts" },
      { "key": "companies.create", "description": "Create companies" },
      { "key": "companies.read",   "description": "View companies" },
      { "key": "deals.create",    "description": "Create deals" },
      { "key": "deals.read",      "description": "View deals" },
      { "key": "deals.update",    "description": "Edit deals" },
      { "key": "deals.delete",    "description": "Delete deals" }
    ]
  }
}

Schema sync

Every manifest install diffs your dataContract against the live PostgreSQL schema and applies the minimum DDL in a single transaction per table:

Change DDL
New entity CREATE TABLE
New field ALTER TABLE ... ADD COLUMN
Field type changed ALTER TABLE ... ALTER COLUMN ... TYPE with USING cast
required changed SET / DROP NOT NULL
defaultValue changed SET / DROP DEFAULT
enumValues updated DROP CONSTRAINT + ADD CONSTRAINT CHECK
Field removed DROP COLUMN ... CASCADE
Entity removed DROP TABLE ... CASCADE

Changes are applied in a safe order: drop constraints, alter types, add columns, nullability, defaults, add constraints, drop columns.

The Schema Sync Engine drops columns removed from the manifest and can drop orphaned tables. Only id, created_at, and updated_at are protected.
PreviousBackend & RPCNextREST API

On this page

Top-level fields
dataContract[]
dataContract[].fields[]
Field types
Relationships and constraints
actions[]
permissions
configSchema
Full example manifest
Schema sync