React SDK
@rootcx/sdk provides React hooks, components, and a direct HTTP client for interacting with the RootCX Core from your frontend.
Setup
Copy
npm install @rootcx/sdk
Requires React 18+. ESM-only. Works with Vite, Next.js, and other modern bundlers.
Copy
import { RuntimeProvider } from "@rootcx/sdk" ;
createRoot (document. getElementById ( "root" ) ! ). render (
< RuntimeProvider baseUrl = "https://<your-ref>.rootcx.com" >
< App />
</ RuntimeProvider >
);
All hooks require a RuntimeProvider ancestor.
Hooks
useAuth
Return
Type
Description
user
AuthUser | null
Current authenticated user
isAuthenticated
boolean
True if user is not null
loading
boolean
True during auth operations
authMode
AuthMode | null
Server auth config (providers, password enabled, magic link enabled)
login
(email, password) => Promise<void>
Password login
register
(data: RegisterInput) => Promise<void>
Create account
logout
() => Promise<void>
Destroy session
oidcLogin
(providerId) => Promise<void>
Redirect to OIDC provider
magicLinkConsume
(token) => Promise<void>
Consume a magic link token
useAppCollection
Copy
useAppCollection < T >(appId: string, entity: string, query ?: QueryOptions)
Return
Type
Description
data
T[]
Records matching query
total
number
Total count (ignoring limit/offset)
loading
boolean
error
string | null
create
(data) => Promise<T>
Create one record
bulkCreate
(data[]) => Promise<T[]>
Create multiple records
update
(id, data) => Promise<T>
Partial update
remove
(id) => Promise<void>
Delete
refetch
() => void
Re-fetch manually
useAppRecord
Copy
useAppRecord < T >(appId: string, entity: string, recordId: string | null )
Return
Type
Description
data
T | null
The record (null if not loaded or recordId is null)
loading
boolean
error
string | null
update
(data) => Promise<T>
Partial update
remove
() => Promise<void>
Delete
refetch
() => void
If recordId is null, nothing is fetched.
useCoreCollection
Copy
useCoreCollection < T >(entity: string)
Read-only access to platform collections (currently users). Hits GET /api/v1/users directly.
Return
Type
Description
data
T[]
Records
loading
boolean
error
string | null
refetch
() => void
No mutations. Core collections are managed by the platform.
Do not use useAppCollection with core:users as the entity — it hits the per-app collections API and returns 404. Use useCoreCollection("users") instead.
usePermissions
Return
Type
Description
roles
string[]
Resolved roles for current user
permissions
string[]
Flat list of permission keys
can
(key) => boolean
Check permission (supports wildcards: *, app:crm:*)
loading
boolean
error
string | null
refetch
() => void
Client-side only. The Core enforces RBAC server-side on every request.
useCrons
Copy
useCrons (appId: string)
Return
Type
Description
data
CronSchedule[]
All crons for this app
loading
boolean
error
string | null
create
(input: CreateCronInput) => Promise<CronSchedule>
Create a cron
update
(id, patch: UpdateCronInput) => Promise<CronSchedule>
Update
remove
(id) => Promise<void>
Delete
trigger
(id) => Promise<{ msgId: number }>
Fire immediately
refetch
() => void
useIntegration
Copy
useIntegration (integrationId: string)
Return
Type
Description
connected
boolean
True if at least one connection exists
connections
Connection[]
All connections for this integration
loading
boolean
connect
() => Promise<void | { type: "credentials", schema }>
Start OAuth (void = redirect) or get credential schema
submitCredentials
(creds) => Promise<void>
Submit manual credentials
remove
(connectionId: string) => Promise<void>
Remove connection
call
(action, input?) => Promise<unknown>
Execute an integration action
useIdentity
Copy
useIdentity < T >(identityKind: string, query ?: QueryOptions)
Federated query across all apps sharing the same identityKind.
Return
Type
Description
data
IdentityRecord<T>[]
Records with _source: { app, entity } metadata
total
number
Total count
loading
boolean
error
string | null
refetch
() => void
useRuntimeClient
Copy
const client = useRuntimeClient ();
Returns the RuntimeClient instance from context. Use for imperative API calls in event handlers.
Components
AuthGate
Pre-built login/registration UI. Wrap your app to show auth when not authenticated.
Copy
< AuthGate appTitle = "My App" >
{ ({ user , logout }) => < MyApp /> }
</ AuthGate >
Prop
Type
Description
appTitle
string
Shown in form header
renderLoading
ReactNode
Custom loading state
renderForm
(props: AuthFormSlotProps) => ReactNode
Custom form (receives mode, error, submitting, onSubmit, providers, passwordLoginEnabled, onOidcLogin)
children
({ user, logout }) => ReactNode
Render function when authenticated
Authorized
Conditionally render based on RBAC permission.
Copy
< Authorized permission = "app:crm:contacts.delete" fallback ={ < span >No access</ span > } >
< DeleteButton />
</ Authorized >
Prop
Type
Description
permission
string
Required permission key
fallback
ReactNode
Rendered if denied
children
ReactNode
Rendered if allowed
PermissionsProvider
Share a single permissions fetch across multiple Authorized components.
Copy
< PermissionsProvider >
< Authorized permission = "..." >...</ Authorized >
< Authorized permission = "..." >...</ Authorized >
</ PermissionsProvider >
QueryOptions
Used by useAppCollection, useAppRecord, and useIdentity.
Field
Type
Description
where
WhereClause
Filter conditions
orderBy
string
Sort column
order
"asc" | "desc"
Sort direction
limit
number
Max records
offset
number
Skip count
linked
boolean | string[]
Resolve federated identity links
Where operators
Operator
Description
$eq
Equal (also works as direct value: { status: "active" })
$ne
Not equal
$gt, $gte
Greater than (or equal)
$lt, $lte
Less than (or equal)
$like, $ilike
Pattern match (case-sensitive / insensitive)
$in, $nin
In / not in array
$contains
Array field contains value
$isNull
Is null check
$and, $or, $not
Logical combinators
RuntimeClient
Direct HTTP client for non-React code or imperative use.
Copy
import { RuntimeClient } from "@rootcx/sdk" ;
const client = new RuntimeClient ({ baseUrl: "https://<your-ref>.rootcx.com" });
Constructor options
Option
Type
Default
Description
baseUrl
string
Auto-detected
Core API URL. Checks VITE_ROOTCX_URL, then window.location.origin, then http://localhost:9100.
accessToken
string
null
Initial Bearer token (JWT or share token).
persist
boolean
true
If false, tokens are never read from or written to localStorage. Use for public share sessions.
autoRefresh
boolean
true
If false, 401 responses are returned without attempting a token refresh. Required for share-token sessions.
Public share visitor example:
Copy
const client = new RuntimeClient ({ accessToken: shareToken, persist: false , autoRefresh: false });
const info = await client. getPublicShareInfo (); // → { appId, context }
const data = await client. rpc (info.appId, "get_board" , { board_id: info.context.board_id });
Auth
Method
Signature
login
(email, password) => Promise<LoginResponse>
register
(data: RegisterInput) => Promise<{ user: AuthUser }>
magicLinkConsume
(token) => Promise<LoginResponse>
logout
() => Promise<void>
me
() => Promise<AuthUser>
getAuthMode
() => Promise<AuthMode>
Data
Method
Signature
listRecords
(appId, entity, opts?) => Promise<T[]>
queryRecords
(appId, entity, query: QueryOptions) => Promise<{ data: T[], total }>
createRecord
(appId, entity, data) => Promise<T>
bulkCreateRecords
(appId, entity, data[]) => Promise<T[]>
getRecord
(appId, entity, id) => Promise<T>
updateRecord
(appId, entity, id, data) => Promise<T>
deleteRecord
(appId, entity, id) => Promise<void>
identityQuery
(kind, query?) => Promise<{ data: T[], total }>
RPC
Method
Signature
rpc
(appId, method, params?) => Promise<unknown>
Roles and permissions
Method
Signature
listRoles
() => Promise<RoleDefinition[]>
createRole
(data) => Promise<{ message }>
updateRole
(name, data) => Promise<{ message }>
deleteRole
(name) => Promise<{ message }>
listRoleAssignments
() => Promise<RoleAssignment[]>
assignRole
(userId, role) => Promise<{ message }>
revokeRole
(userId, role) => Promise<{ message }>
getPermissions
(userId?) => Promise<EffectivePermissions>
getAvailablePermissions
() => Promise<PermissionDeclaration[]>
Integrations
Method
Signature
callIntegration
(id, action, input?) => Promise<unknown>
bindIntegration
(appId, integrationId, connectionId) => Promise<void>
unbindIntegration
(appId, integrationId) => Promise<void>
listConnections
(integrationId) => Promise<Connection[]>
integrationAuthStatus
(id) => Promise<{ connected, connectionCount }>
integrationAuthStart
(id) => Promise<{ redirectUrl? }>
integrationAuthSubmit
(id, credentials, label?) => Promise<void>
integrationAuthDisconnect
(id) => Promise<void>
Jobs
Method
Signature
enqueueJob
(appId, payload) => Promise<{ msg_id }>
listJobs
(appId, opts?) => Promise<Job[]>
Crons
Method
Signature
listCrons
(appId) => Promise<CronSchedule[]>
createCron
(appId, input: CreateCronInput) => Promise<CronSchedule>
updateCron
(appId, id, patch) => Promise<CronSchedule>
deleteCron
(appId, id) => Promise<void>
triggerCron
(appId, id) => Promise<{ msgId }>
Webhooks
Method
Signature
listWebhooks
(appId) => Promise<Webhook[]>
Agents
Copy
const result = await client. invokeAgent (appId, opts, onEvent, signal ? );
Parameter
Type
Description
appId
string
The agent's app ID.
opts
InvokeAgentOptions
{ message: string, sessionId?: string, fileIds?: string[] }
onEvent
(event: AgentEvent) => void
Callback fired on each SSE event.
signal
AbortSignal
Optional. Cancel the invocation.
Returns Promise<AgentDoneEvent> with { type: "done", response: string, sessionId: string, tokens: number }.
Event types (discriminated union on type):
Event
Key fields
chunk
delta, sessionId
tool_call_started
callId, toolName, input, sessionId
tool_call_completed
callId, toolName, output, error, durationMs, sessionId
approval_required
approvalId, toolName, args, reason, sessionId
session_compacted
summary, sessionId
sub_agent_chunk
appId, delta
done
response, sessionId, tokens
error
error, sessionId
Throws RuntimeApiError if the HTTP call fails, the stream has no body, or the agent errors without completing.
All event interfaces are exported from @rootcx/sdk: AgentEvent, AgentDoneEvent, AgentChunkEvent, AgentErrorEvent, AgentToolCallStartedEvent, AgentToolCallCompletedEvent, AgentApprovalRequiredEvent, AgentSessionCompactedEvent, AgentSubAgentChunkEvent.
Shares
Method
Signature
createPublicShare
(appId, opts: { context: Record<string, unknown> }) => Promise<{ id, url, token, tokenPrefix, context, createdAt }>
revokePublicShare
(appId, shareId) => Promise<{ message: string }>
listPublicShares
(appId) => Promise<PublicShareListing[]>
getPublicShareInfo
() => Promise<{ appId: string, context: Record<string, unknown> }>
The token in createPublicShare is returned once at creation time and never shown again. Store it immediately.
getPublicShareInfo resolves a share token (passed as accessToken in the constructor) to its app and context. Use it from anonymous/public sessions.
Low-level
Method
Signature
getBaseUrl
() => string
getAccessToken
() => string | null
setTokens
(access, refresh) => void
authFetch
(url, init?) => Promise<Response>
fetchJson
(url, init?) => Promise<T>
Types
Copy
interface AuthUser {
id : string ;
email : string ;
displayName : string | null ;
createdAt : string ;
}
interface AuthMode {
authRequired : boolean ;
setupRequired : boolean ;
passwordLoginEnabled : boolean ;
magicLinkEnabled : boolean ;
providers : OidcProvider [];
}
interface OidcProvider { id : string ; displayName : string }
interface RegisterInput { email : string ; password : string ; displayName ?: string }
interface LoginResponse { accessToken : string ; refreshToken : string ; expiresIn : number ; user : AuthUser }
interface EffectivePermissions { roles : string []; permissions : string [] }
interface RoleDefinition { name : string ; description : string | null ; inherits : string []; permissions : string [] }
interface RoleAssignment { userId : string ; role : string ; assignedAt : string }
interface PermissionDeclaration { key : string ; description : string }
interface QueryOptions {
where ?: WhereClause ;
orderBy ?: string ;
order ?: "asc" | "desc" ;
limit ?: number ;
offset ?: number ;
linked ?: boolean | string [];
}
interface QueryResult < T > { data : T []; total : number }
type IdentityRecord < T > = T & { _source : { app : string ; entity : string } }
interface CronSchedule {
id : string ; appId : string ; name : string ; schedule : string ;
timezone : string | null ; payload : Record < string , unknown >;
overlapPolicy : "skip" | "queue" ; enabled : boolean ;
pgJobId : number | null ; createdBy : string | null ;
createdAt : string ; updatedAt : string ;
}
interface CreateCronInput { name : string ; schedule : string ; timezone ?: string ; payload ?: Record < string , unknown >; overlapPolicy ?: "skip" | "queue" }
interface UpdateCronInput { schedule ?: string ; payload ?: Record < string , unknown >; overlapPolicy ?: "skip" | "queue" ; enabled ?: boolean }
interface Job { msg_id : number ; app_id : string ; payload : Record < string , unknown >; user_id : string | null ; read_ct : number ; enqueued_at : string }
interface IntegrationSummary { id : string ; name : string ; version : string ; description : string ; actions : ActionDefinition []; configSchema : Record < string , unknown >; webhooks : string [] }