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
RootCXDevelopersApi Reference

REST API Reference

Complete reference for the RootCX Core HTTP API.

Overview

Property Value
Base URL https://<your-ref>.rootcx.com (or http://localhost:9100 if self-hosting)
Protocol HTTP/1.1
Format JSON (UTF-8)
Max body 50 MB

All /api/v1/* routes accept and return JSON. The deploy endpoint accepts multipart/form-data with an archive field (tar.gz). The logs endpoint returns text/event-stream.

Authentication

Pass a JWT access token as a Bearer token in the Authorization header:

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

All /api/v1/* endpoints require a valid token except the auth endpoints (register, login, mode). Requests to protected endpoints without a token receive a 401 Unauthorized response.

System

Method Path Description
GET /health Health check -- returns {status:'ok'}
GET /api/v1/status Runtime status (postgres, runtime, forge)

GET /api/v1/status

{
  "runtime": { "version": "1.0.0", "state": "Online" },
  "postgres": { "state": "Online", "port": 5480 },
  "forge": { "state": "Offline", "port": null }
}

State is one of: Online, Offline, Starting, Stopping, Error.

Auth

Method Path Description
POST /api/v1/auth/register Register a new user
POST /api/v1/auth/login Login and receive tokens
POST /api/v1/auth/refresh Refresh an expired access token
POST /api/v1/auth/logout Invalidate session
GET /api/v1/auth/me Get current authenticated user
GET /api/v1/auth/mode Get current auth mode
GET /api/v1/users List all users

POST /api/v1/auth/register

// Request
{
  "username": "alice",
  "password": "Str0ngPass!x",
  "email": "alice@example.com",    // optional
  "display_name": "Alice Martin"   // optional
}

// Response 201
{
  "user": {
    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "username": "alice",
    "email": "alice@example.com",
    "display_name": "Alice Martin",
    "created_at": "2024-01-15T10:30:00+00:00"
  }
}

Password requirements: minimum 10 characters, at least one uppercase letter, one lowercase letter, and one digit.

The first user to register is automatically assigned the admin role on the core app. Registration does not return tokens — call the login endpoint after registration to obtain an access token.

GET /api/v1/auth/mode

// Response 200
{ "authRequired": true }

POST /api/v1/auth/login

// Request
{ "username": "alice", "password": "Str0ngPass!x" }

// Response 200
{
  "accessToken": "eyJ...",
  "refreshToken": "eyJ...",
  "expiresIn": 900,
  "user": {
    "id": "3fa85f64-...",
    "username": "alice",
    "email": "alice@example.com",
    "display_name": "Alice Martin",
    "created_at": "2024-01-15T10:30:00+00:00"
  }
}

POST /api/v1/auth/refresh

// Request
{ "refreshToken": "eyJ..." }

// Response 200
{ "accessToken": "eyJ...", "expiresIn": 900 }

POST /api/v1/auth/logout

// Request
{ "refreshToken": "eyJ..." }

// Response 200
{ "message": "logged out" }

Apps

Method Path Description
GET /api/v1/apps List all installed applications
POST /api/v1/apps Install an application from a manifest
DELETE /api/v1/apps/{appId} Uninstall an application

POST /api/v1/apps -- Install app

// Request body: AppManifest object
{
  "appId": "crm",
  "name": "My CRM",
  "version": "1.0.0",
  "dataContract": [...],
  "permissions": {...}
}

// Response 200
{
  "message": "app 'crm' installed"
}

[!INFO] Idempotent install Posting a manifest for an existing app ID triggers a schema sync -- new tables and columns are added, changed types are migrated, and RBAC policies are updated. Existing data is preserved.

Data (CRUD)

Method Path Description
GET /api/v1/apps/{appId}/collections/{entity} List all records
POST /api/v1/apps/{appId}/collections/{entity} Create a record
GET /api/v1/apps/{appId}/collections/{entity}/{id} Get a record by ID
PATCH /api/v1/apps/{appId}/collections/{entity}/{id} Partially update a record
DELETE /api/v1/apps/{appId}/collections/{entity}/{id} Delete a record

Record shape

{
  "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "first_name": "Alice",
  "last_name": "Martin",
  "email": "alice@acme.com",
  "tags": ["vip", "enterprise"],
  "created_at": "2024-01-15T10:30:00Z",
  "updated_at": "2024-01-15T10:30:00Z"
}

Workers

Method Path Description
POST /api/v1/apps/{appId}/deploy Deploy worker code (multipart, archive field, tar.gz)
POST /api/v1/apps/{appId}/worker/start Start the worker process
POST /api/v1/apps/{appId}/worker/stop Stop the worker process
GET /api/v1/apps/{appId}/worker/status Get worker status
POST /api/v1/apps/{appId}/rpc Invoke a worker RPC method
SSE /api/v1/apps/{appId}/logs Stream live worker logs

POST /api/v1/apps/{appId}/rpc

// Request
{
  "method": "sendWelcomeEmail",
  "params": { "contactId": "f47ac10b..." }
}

// Response 200 -- the handler's return value is returned directly
{ "sent": true }

// Error response
{ "error": "Failed to connect to SMTP server" }

GET /api/v1/apps/{appId}/worker/status

{
  "app_id": "crm",
  "status": "running"
}

Status is one of: starting, running, stopping, stopped, crashed.

Jobs

Method Path Description
POST /api/v1/apps/{appId}/jobs Enqueue a background job
GET /api/v1/apps/{appId}/jobs List jobs (filter by status)
GET /api/v1/apps/{appId}/jobs/{jobId} Get job by ID

POST /api/v1/apps/{appId}/jobs

// Request
{
  "payload": { "type": "send_report", "userId": "..." }
}

// Response 201
{ "job_id": "a1b2c3d4-..." }

// Job object (from GET)
{
  "id": "a1b2c3d4-...",
  "app_id": "crm",
  "status": "completed",
  "payload": { "type": "send_report", "userId": "..." },
  "result": { "sent": true },
  "error": null,
  "attempts": 1
}

Secrets

Method Path Description
POST /api/v1/apps/{appId}/secrets Set a secret (idempotent)
GET /api/v1/apps/{appId}/secrets List secret key names (not values)
DELETE /api/v1/apps/{appId}/secrets/{key} Delete a secret
// POST /api/v1/apps/crm/secrets
// Request
{ "key": "OPENAI_API_KEY", "value": "sk-..." }
// Response
{ "message": "secret 'OPENAI_API_KEY' set" }

// GET /api/v1/apps/crm/secrets
// Response -- key names only, never values
["OPENAI_API_KEY", "STRIPE_SECRET_KEY", "SMTP_PASSWORD"]

Platform Secrets

Method Path Description
POST /api/v1/platform/secrets Set a platform-wide secret
GET /api/v1/platform/secrets List platform secret key names
DELETE /api/v1/platform/secrets/{key} Delete a platform secret

Platform secrets are shared across integrations. App-level secrets (above) are scoped to a single app.

RBAC

Method Path Description
GET /api/v1/apps/{appId}/roles List all roles
POST /api/v1/apps/{appId}/roles Create a role
PATCH /api/v1/apps/{appId}/roles/{roleName} Update a role
DELETE /api/v1/apps/{appId}/roles/{roleName} Delete a role
GET /api/v1/apps/{appId}/roles/assignments List user-role assignments
POST /api/v1/apps/{appId}/roles/assign Assign a role to a user
POST /api/v1/apps/{appId}/roles/revoke Revoke a role from a user
GET /api/v1/apps/{appId}/permissions Current user's effective permissions
GET /api/v1/apps/{appId}/permissions/available List all available permission keys
GET /api/v1/apps/{appId}/permissions/{userId} Specific user's permissions
// POST /api/v1/apps/crm/roles/assign
{ "userId": "3fa85f64-...", "role": "admin" }

// GET /api/v1/apps/crm/permissions
{
  "roles": ["admin"],
  "permissions": ["contacts.create", "contacts.read", "contacts.update", "contacts.delete", "deals.create", "deals.read", "deals.update", "deals.delete"]
}

Audit

Method Path Description
GET /api/v1/audit Query the audit log
# Query parameters
$ GET /api/v1/audit
  ?app_id=crm         # Filter by app (matches table_schema)
  &entity=contacts    # Filter by table name
  &limit=100          # Max results (default 100, max 1000)
[
  {
    "id": 1001,
    "table_schema": "crm",
    "table_name": "contacts",
    "record_id": "f47ac10b-...",
    "operation": "UPDATE",
    "old_record": { "email": "alice@old.com" },
    "new_record": { "email": "alice@acme.com" },
    "changed_at": "2024-01-15T10:30:00Z"
  }
]

Error format

All errors return a JSON body with an error field and the appropriate HTTP status code:

{ "error": "human-readable error message" }
Status Meaning Common causes
400 Bad Request Invalid JSON, missing required fields, validation error, duplicate username/app ID
401 Unauthorized Missing or invalid Bearer token
403 Forbidden Valid token but RBAC policy denies the action
404 Not Found Record doesn't exist or you don't have ownership access
500 Internal Server Error Unexpected database or runtime error
503 Service Unavailable PostgreSQL or daemon not ready yet
PreviousManifest ReferenceNextSelf-Hosting

On this page

Overview
Authentication
System
Auth
Apps
Data (CRUD)
Workers
Jobs
Secrets
Platform Secrets
RBAC
Audit
Error format