Skip to content

REST API

The Callora host is an ASP.NET application built on minimal APIs (MapGet/MapPost/MapPut/MapDelete, grouped with MapGroup). This page catalogues the real HTTP endpoints, grouped by area.

Conventions

  • Base paths. Operator/admin resources live under /api/*. Authentication lives under /api/auth and /workspace/auth. Workspace-facing public routes live under /workspace/*. The server-rendered public surface is /surface/render. The published UI-asset manifest is served under /manifests/*.
  • Auth model. Login (/api/auth/login) issues a JWT carried in an auth cookie. Roles: SuperAdmin is global; Admin is scoped per workspace. Fine-grained access is enforced with permission claims (for example plugin.read, workspace.update). A SuperAdmin bypasses per-permission checks. Workspace-scoped endpoints additionally bind the request to a workspaceKey and verify the caller's access to that workspace at runtime.
  • Reserved route prefixes. The public workspace catch-all treats these prefixes as reserved (not routed to a workspace): api, swagger, workspace, health, plugin-assets, manifests, _nuxt. Requests under /admin are redirected to the admin shell.

The permission constants shown below are the string keys from BackendPermissionKeys. "Authenticated" means the group requires a valid session but no specific permission. "Anonymous" means no session is required.

Authentication

MethodPathPurposeAuth
POST/api/auth/loginShared admin login; omit workspaceKey for a platform-scoped operator session, name it for a workspace-scoped session. Sets the auth cookie and returns a bearer token.Anonymous (rate-limited)
POST/api/auth/logoutClears the auth cookie.Anonymous (rate-limited)
GET/api/auth/meReturns the current identity (user id, display name, email, role).Authenticated
POST/workspace/auth/loginDeprecated alias of /api/auth/login, retained for the existing workspace shell.Anonymous (rate-limited)

Operator / Admin console

Admin context

MethodPathPurposeAuth
GET/api/admin/contextConsole bootstrap context for the current session.Authenticated

Plugins

Group /api/plugins.

MethodPathPurposeAuth
GET/api/plugins/List runtime plugins.plugin.read
GET/api/plugins/installedList installed plugin records.plugin.read
GET/api/plugins/signature-reportSignature verification report per installed plugin.plugin.read
GET/api/plugins/auditPlugin lifecycle audit log.plugin.read
GET/api/plugins/contracts/supportContract-version support status (v2 supported, v1 deprecated, v0 removed).plugin.read
GET/api/plugins/contracts/compatibilityContract compatibility of installed plugins.plugin.read
GET/api/plugins/security/trusted-signersConfigured trusted plugin signers.plugin.read
GET/api/plugins/workspaces/{workspaceKey}/entitlements/{pluginId}Plugin entitlement for a workspace.plugin.read
GET/api/plugins/tenants/{tenantId}/entitlements/{pluginId}Plugin entitlement for a tenant.plugin.read
POST/api/plugins/installInstall a plugin.plugin.create
POST/api/plugins/install/localInstall a plugin from a local path.plugin.create
POST/api/plugins/install/nugetInstall a plugin from a NuGet package.plugin.create
POST/api/plugins/{pluginId}/update/nugetUpdate a plugin from NuGet.plugin.create
POST/api/plugins/{pluginId}/update/localUpdate a plugin from a local path.plugin.create
POST/api/plugins/{pluginId}/activateActivate a plugin (hot, no restart).plugin.execute
POST/api/plugins/{pluginId}/deactivateDeactivate a plugin.plugin.execute
DELETE/api/plugins/{pluginId}Uninstall a plugin.plugin.delete

Plugin admin extensions

Group /api/ext/admin. Plugins contribute admin navigation and routes; the host serves them dynamically.

MethodPathPurposeAuth
GET/api/ext/admin/navigationPlugin-contributed admin navigation, filtered per-item by the item's required permission.Authenticated
GET/POST/PUT/DELETE/api/ext/admin/plugins/{pluginId}/{**routePath}Proxy to a plugin's admin route; each route declares its own required permission, checked at runtime.Per-route permission

RBAC

Group /api/security/rbac.

MethodPathPurposeAuth
GET/api/security/rbac/rolesList roles.role.read
GET/api/security/rbac/permissionsList available permissions (includes plugin-contributed ones).role.read
PUT/api/security/rbac/roles/{role}Create or update a role.role.update
DELETE/api/security/rbac/roles/{role}Delete a role.role.update
GET/api/security/rbac/usersList RBAC user-role assignments.role.read
PUT/api/security/rbac/users/{userId}Assign roles to a user.role.update
DELETE/api/security/rbac/users/{userId}Remove a user's role assignments.role.update

Users

Group /api/users.

MethodPathPurposeAuth
GET/api/users/List users.user.read
GET/api/users/{userId}Get a user.user.read
POST/api/users/Create a user (also requires operator scope at runtime).user.create
PUT/api/users/{userId}Update a user.user.update
DELETE/api/users/{userId}Delete a user.user.delete
GET/api/users/{userId}/data-exportExport a user's data (GDPR subject access).user.read

Tenants

Group /api/tenants.

MethodPathPurposeAuth
GET/api/tenants/List tenants.tenant.read
GET/api/tenants/{tenantKey}Get a tenant.tenant.read
POST/api/tenants/Create a tenant.tenant.create
POST/api/tenants/{tenantKey}/activateActivate a tenant.tenant.update
POST/api/tenants/{tenantKey}/suspendSuspend a tenant.tenant.update
DELETE/api/tenants/{tenantKey}Delete a tenant.tenant.delete

System configuration

Group /api/config.

MethodPathPurposeAuth
GET/api/config/definitionsConfiguration field definitions (host + plugin).config.read
GET/api/config/effectiveEffective configuration values (workspace-scoped).config.read
PUT/api/config/valuesUpsert configuration values (workspace-scoped; access verified at runtime).config.update

Features

Group /api/features.

MethodPathPurposeAuth
GET/api/features/List feature flags.Authenticated
GET/api/features/{key}Get a single feature flag.Authenticated

Business events

MethodPathPurposeAuth
GET/api/events/catalogThe registered business-event catalogue.flow.read

Jobs

Group /api/jobs.

MethodPathPurposeAuth
GET/api/jobs/List background jobs (operators see all; workspace users see their workspace only).job.read

Notifications

Group /api/notifications.

MethodPathPurposeAuth
GET/api/notifications/List notifications (workspace-scoped).notification.read
PUT/api/notifications/{id}/readMark a notification read (access verified at runtime).notification.read

Media

Group /api/media.

MethodPathPurposeAuth
GET/api/media/List media (workspace-scoped).media.read
POST/api/media/Upload media (workspace-scoped).media.manage
GET/api/media/{id}/contentDownload media content.media.read
DELETE/api/media/{id}Delete media.media.manage

Custom fields

Group /api/custom-fields.

MethodPathPurposeAuth
GET/api/custom-fields/definitionsCustom-field definitions.customfield.read
GET/api/custom-fields/{entityName}/{entityId}Custom-field values for an entity.customfield.read
PUT/api/custom-fields/{entityName}/{entityId}Upsert custom-field values for an entity.customfield.update

Flows

Group /api/flows.

MethodPathPurposeAuth
GET/api/flows/List flows (workspace-scoped).flow.read
POST/api/flows/Create a flow.flow.manage
PUT/api/flows/{id}Update a flow.flow.manage
DELETE/api/flows/{id}Delete a flow.flow.manage

Webhooks

Group /api/webhooks.

MethodPathPurposeAuth
GET/api/webhooks/List webhook subscriptions (workspace-scoped).webhook.read
POST/api/webhooks/Create a webhook subscription.webhook.manage
PUT/api/webhooks/{id}/activationActivate/deactivate a webhook.webhook.manage
DELETE/api/webhooks/{id}Delete a webhook.webhook.manage

Entitlements

Group /api/entitlements.

MethodPathPurposeAuth
GET/api/entitlements/List plugin entitlements.plugin.read
PUT/api/entitlements/Upsert an entitlement.plugin.execute
POST/api/entitlements/syncSync entitlements from the marketplace/provider.plugin.execute

Workspaces and surfaces

Workspaces

Group /api/workspaces.

MethodPathPurposeAuth
GET/api/workspaces/List workspaces.workspace.read
GET/api/workspaces/{workspaceKey}Get a workspace.workspace.read
PUT/api/workspaces/{workspaceKey}Create or update a workspace.workspace.update
DELETE/api/workspaces/{workspaceKey}Delete a workspace.workspace.delete
PUT/api/workspaces/{workspaceKey}/surface-access-policySet the surface access policy ({ "policy": "Public" | "Authenticated" }; unknown value → 400).workspace.update
GET/api/workspaces/{workspaceKey}/membersList workspace members (cursor-paginated).workspace.read
PUT/api/workspaces/{workspaceKey}/members/{userId}Add or update a member.workspace.update
DELETE/api/workspaces/{workspaceKey}/members/{userId}Remove a member.workspace.update

Surfaces

Group /api/workspaces/{workspaceKey}/surfaces.

MethodPathPurposeAuth
GET.../surfaces/List a workspace's surfaces.workspace.read
GET.../surfaces/{surfaceKey}Get a surface.workspace.read
PUT.../surfaces/{surfaceKey}Create or update a surface.workspace.update
DELETE.../surfaces/{surfaceKey}Delete a surface. 409 when it has children.workspace.update

A surface upsert carries its place in the tree: parentSurfaceKey (empty for an application root), position among siblings, and requiredClaims for who may see it. A child's publicPathPrefix is its own segment only — the full path is composed from the chain, so moving a subtree does not rewrite its descendants.

Deleting is refused with 409 in two cases, and both mean the same thing — there is a decision to make first: the node still has children (move or delete them), or it is an application root (roots carry host, access mode and identity provider and are removed deliberately).

Themes (operator)

Group /api/themes.

MethodPathPurposeAuth
GET/api/themes/definitionsList theme template definitions.extension.read
PUT/api/themes/definitions/{templateKey}/plugins/{pluginId}/versions/{version}Upsert a theme definition.extension.update
PUT/api/themes/definitions/{templateKey}/plugins/{pluginId}/versions/{version}/activationToggle a theme definition's activation.extension.update
GET/api/themes/workspaces/{workspaceKey}Get a workspace's assigned theme.extension.read
PUT/api/themes/workspaces/{workspaceKey}Assign a theme to a workspace.extension.update
DELETE/api/themes/workspaces/{workspaceKey}Clear a workspace's theme.extension.update
GET/api/themes/workspaces/{workspaceKey}/effectiveEffective theme (resolved chain).extension.read
GET/api/themes/workspaces/{workspaceKey}/settingsTheme setting fields + current values.extension.read
PUT/api/themes/workspaces/{workspaceKey}/settingsUpsert theme setting values.extension.update

Themes (workspace)

Group /workspace/themes.

MethodPathPurposeAuth
GET/workspace/themes/effectiveEffective theme for the caller's workspace (access verified at runtime).extension.read

Public workspace surface

These routes serve the public storefront-style surface and are excluded from the OpenAPI description. Most are unconditionally anonymous; /surface/render and /workspace/public/ui-chain additionally enforce the workspace's surface access policyPublic (default) is anonymous, Authenticated turns anonymous callers away (see Access policy).

MethodPathPurposeAuth
GET/workspace/public/resolveResolve the request host/path to a workspace (returns resolved, workspaceKey).Anonymous
GET/workspace/public/bootstrap.jsJavaScript that sets window.__CALLORA_WORKSPACE_CONTEXT__.Anonymous
GET/workspace/public/contextWorkspace + route context for a given path.Anonymous
GET/workspace/public/ui-chainThe workspace's resolved UI-chain (plugin composition).Anonymous (Public); Authenticated404 for anonymous
GET/workspace/public/themeThe workspace's public theme tokens (valuesByKey).Anonymous
GET/loginRedirect to the workspace shell login for the resolved workspace.Anonymous
GET/surface/renderServer-render the workspace's template chain (falls back to the SPA shell).Anonymous (Public); Authenticated302 /login for anonymous
GET/ and /{**path:nonfile}Catch-all: redirect to the workspace shell, the admin shell (/admin), or 404 for reserved prefixes.Anonymous

Plugin assets and manifests

MethodPathPurposeAuth
GET/manifests/plugin-ui-assets.manifest.jsonThe published UI-asset manifest (route configurable via PluginManifestUrl). Returns 404 until published.Anonymous
GET/admin/{**path:nonfile}Admin-shell SPA fallback (serves the shell's index.html).Anonymous

Published plugin UI assets themselves are served as static files under /plugin-assets/*. See Extension manifests for the manifest format.

Health

MethodPathPurposeAuth
GET/healthLiveness probe. Returns {"status":"ok"} (this JSON body is a contract).Anonymous
GET/readyReadiness probe (checks the database).Anonymous

Dynamic plugin routes

Active plugins contribute their own API routes through the platform's route data source (Shopware-style discovery): activating a plugin adds its routes and deactivating removes them, without a host restart. These routes are not part of this static catalogue because they are defined by the installed plugins.