RootCX
Docs
Pricing
RootCX/RootCXSource Available
Introduction
What is RootCX?Getting StartedHow it Works
Build
ApplicationAI AgentIntegrationDeploying
Platform
CoreAuthenticationRBACData APISecret VaultJob QueueScheduled Jobs (Crons)Audit LogReal-time LogsChannels
Developers
React SDKBackend & RPCManifest ReferenceREST APICLIClaude CodeSelf-Hosting
DocsDevelopersREST API 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 and agent invoke endpoints return 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 auth endpoints (register, login, mode, oidc/providers list). 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

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 (public)
GET /api/v1/users List all users
DELETE /api/v1/users/{id} Delete a user

POST /api/v1/auth/register

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

// Response 201
{
  "user": {
    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "email": "alice@example.com",
    "displayName": "Alice Martin",
    "createdAt": "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 built-in admin role. Registration does not return tokens -- call the login endpoint after.

GET /api/v1/auth/mode

{
  "authRequired": true,
  "setupRequired": false,
  "passwordLoginEnabled": true,
  "providers": [
    { "id": "okta", "displayName": "Okta SSO" }
  ]
}

POST /api/v1/auth/login

// Request
{ "email": "alice@example.com", "password": "Str0ngPass!x" }

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

DELETE /api/v1/users/{id}

Delete a user. Returns 400 if this is the last admin (prevents lockout).

OIDC

Method Path Description
GET /api/v1/auth/oidc/providers List enabled providers (public)
POST /api/v1/auth/oidc/providers Create/update provider (admin)
DELETE /api/v1/auth/oidc/providers/{id} Delete provider (admin, ?force=true)
GET /api/v1/auth/oidc/{provider_id}/authorize Start browser auth flow (?redirect_uri=...)
GET /api/v1/auth/oidc/callback Authorization callback
POST /api/v1/auth/oidc/token-exchange Server-to-server token exchange

See Authentication for provider configuration details.

POST /api/v1/auth/oidc/token-exchange

// Request
{ "providerId": "okta", "idToken": "eyJhbGciOiJSUzI1..." }

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

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 (cleans secrets, jobs, filesystem)

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" }
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

Unknown entities return 404 (not 500). System columns id, created_at, updated_at are auto-managed.

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 }

RPC timeout: 30 seconds.

Worker status values

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 active jobs (?archived=true for completed)

Jobs are backed by pgmq with a 120-second visibility timeout. Unacknowledged jobs are automatically re-queued.

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

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

// Response 201
{ "msg_id": 42 }

Job object

{
  "msg_id": 42,
  "app_id": "crm",
  "payload": { "type": "send_report", "userId": "..." },
  "user_id": "3fa85f64-...",
  "read_ct": 1,
  "enqueued_at": "2024-01-15T10:30:00Z"
}

Crons

Method Path Description
POST /api/v1/apps/{appId}/crons Create a scheduled cron
GET /api/v1/apps/{appId}/crons List all crons for an app
PATCH /api/v1/apps/{appId}/crons/{id} Update a cron
DELETE /api/v1/apps/{appId}/crons/{id} Delete a cron
POST /api/v1/apps/{appId}/crons/{id}/trigger Fire a cron immediately

Crons are backed by pg_cron. Each tick enqueues a job into the same pgmq queue used by one-shot jobs, dispatched to the worker's onJob handler.

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

// Request
{
  "name": "daily-check",
  "schedule": "0 9 * * *",
  "timezone": "America/New_York",
  "payload": { "task": "check_replies" },
  "overlapPolicy": "skip"
}

// Response 201
{
  "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "appId": "crm",
  "name": "daily-check",
  "schedule": "0 9 * * *",
  "timezone": "America/New_York",
  "payload": { "task": "check_replies" },
  "overlapPolicy": "skip",
  "enabled": true,
  "pgJobId": 7,
  "createdBy": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "createdAt": "2024-01-15T10:30:00Z",
  "updatedAt": "2024-01-15T10:30:00Z"
}

Schedule formats:

  • Standard 5-field cron: * * * * * (minute hour day-of-month month day-of-week)
  • Seconds interval: 10 seconds (1-59, cannot combine with cron fields)
  • $ in day-of-month = last day of the month

All times are GMT unless timezone is set.

Overlap policy: "skip" (default) drops the job if a previous one is still queued. "queue" enqueues regardless.

PATCH /api/v1/apps/{appId}/crons/{id}

// Request -- all fields optional
{ "schedule": "*/5 * * * *", "enabled": false }

// Response 200
{ "id": "f47ac10b-...", "schedule": "*/5 * * * *", "enabled": false, ... }

POST /api/v1/apps/{appId}/crons/{id}/trigger

Manually fires the cron once, bypassing the schedule. Returns the enqueued job's message ID.

// Response 200
{ "msgId": 42 }

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

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 are scoped to a single app.

RBAC

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

See RBAC for full request/response details.

Agents

Method Path Description
GET /api/v1/agents List all agents
GET /api/v1/apps/{appId}/agent Get agent details
PATCH /api/v1/agents/{appId} Update agent name/description
DELETE /api/v1/agents/{appId} Delete agent
POST /api/v1/apps/{appId}/agent/invoke Invoke agent (SSE stream)
GET /api/v1/apps/{appId}/agent/sessions List sessions (?limit=100&offset=0)
GET /api/v1/apps/{appId}/agent/sessions/{sessionId} Get session with messages
GET /api/v1/apps/{appId}/agent/sessions/{sessionId}/events Get session event timeline
GET /api/v1/apps/{appId}/agent/approvals List pending approvals
POST /api/v1/apps/{appId}/agent/approvals/{approvalId} Reply to approval
SSE /api/v1/agents/stream Fleet-wide event stream

POST /api/v1/apps/{appId}/agent/invoke

// Request
{ "message": "What are the open orders?", "session_id": "optional-uuid" }

Returns SSE stream. See Build an AI Agent for event types.

POST /api/v1/apps/{appId}/agent/approvals/{approvalId}

{ "action": "approve" }
// or
{ "action": "reject", "reason": "Too risky" }

Integrations

Method Path Description
GET /api/v1/integrations List installed integrations
GET /api/v1/integrations/catalog List available integrations
POST /api/v1/integrations/catalog/{id}/deploy Deploy integration
DELETE /api/v1/integrations/catalog/{id} Undeploy integration
PUT /api/v1/integrations/{id}/config Save platform config
POST /api/v1/integrations/{id}/actions/{actionId} Execute action
GET /api/v1/integrations/{id}/auth Check auth status
POST /api/v1/integrations/{id}/auth/start Start OAuth flow
POST /api/v1/integrations/{id}/auth/credentials Store credentials
GET /api/v1/integrations/auth/callback OAuth callback

Channels

Method Path Description
GET /api/v1/channels List all channels
POST /api/v1/channels Create a channel
DELETE /api/v1/channels/{channelId} Delete a channel
POST /api/v1/channels/{channelId}/activate Activate and register webhook
POST /api/v1/channels/{channelId}/deactivate Deactivate channel
POST /api/v1/channels/{channelId}/link Create account link token (5-min TTL)
GET /api/v1/channels/{channelId}/identity Check if user linked

Hooks

Method Path Description
GET /api/v1/apps/{appId}/hooks List hooks (?entity=X&operation=Y)
POST /api/v1/apps/{appId}/hooks Create hook
GET /api/v1/apps/{appId}/hooks/{hookId} Get hook
DELETE /api/v1/apps/{appId}/hooks/{hookId} Delete hook

Audit

Method Path Description
GET /api/v1/audit Query the audit log
GET /api/v1/audit?app_id=crm&entity=contacts&limit=100
[
  {
    "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
401 Unauthorized Missing or invalid Bearer token
403 Forbidden Valid token but RBAC policy denies the action
404 Not Found Record or entity doesn't exist
500 Internal Server Error Unexpected database or runtime error
503 Service Unavailable PostgreSQL or daemon not ready yet
PreviousManifest ReferenceNextCLI

On this page

Overview
Authentication
System
Auth
OIDC
Apps
Data (CRUD)
Workers
Jobs
Crons
Secrets
Platform Secrets
RBAC
Agents
Integrations
Channels
Hooks
Audit
Error format