OpenAPI JSONMarkdown Docs

OpenAPI Explorer

Auto-generated OpenAPI definition for all enabled modules.

Default server: http://108.165.128.56:3000/api

Authentication & Accounts

Showing 20 of 36 endpoints
GET/auth/admin/nav
Auth required

Resolve backend chrome bootstrap payload

Returns the backend chrome payload available to the authenticated administrator after applying scope, RBAC, role defaults, and personal sidebar preferences.

Responses

200Backend chrome payload
Content-Type: application/json
{
  "brand": null,
  "groups": [
    {
      "name": "string",
      "items": [
        {
          "href": "string",
          "title": "string"
        }
      ]
    }
  ],
  "settingsSections": [
    {
      "id": "string",
      "label": "string",
      "items": [
        {
          "id": "string",
          "label": "string",
          "href": "string"
        }
      ]
    }
  ],
  "settingsPathPrefixes": [
    "string"
  ],
  "profileSections": [
    {
      "id": "string",
      "label": "string",
      "items": [
        {
          "id": "string",
          "label": "string",
          "href": "string"
        }
      ]
    }
  ],
  "profilePathPrefixes": [
    "string"
  ],
  "grantedFeatures": [
    "string"
  ],
  "roles": [
    "string"
  ],
  "currentOrganization": null
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/auth/admin/nav" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/auth/autologin

Auto sign-in using env-configured demo credentials

When OM_AUTOLOGIN_EMAIL / OM_AUTOLOGIN_PASSWORD are configured, signs the visitor in with those credentials and redirects into the app. Intended for single-tenant demo instances only. Falls back to the login page when disabled or misconfigured.

Responses

200Success response
Content-Type: application/json
"string"
307Redirect into the app (or to /login on failure)
Content-Type: text/html
string

Example

curl -X GET "http://108.165.128.56:3000/api/auth/autologin" \
  -H "Accept: application/json"
POST/auth/feature-check
Auth required

Check feature grants for the current user

Evaluates which of the requested features are available to the signed-in user within the active tenant / organization context.

Request body (application/json)

{
  "features": [
    "string"
  ]
}

Responses

200Evaluation result
Content-Type: application/json
{
  "ok": true,
  "granted": [
    "string"
  ],
  "userId": "string"
}
400Invalid request — features array missing, too large, or contains invalid entries
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
401Authentication required
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/auth/feature-check" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"features\": [
    \"string\"
  ]
}"
GET/auth/features
Auth required

List declared feature flags

Returns all static features contributed by the enabled modules along with their module source.

Responses

200Aggregated feature catalog
Content-Type: application/json
{
  "items": [
    {
      "id": "string",
      "title": "string",
      "module": "string"
    }
  ],
  "modules": [
    {
      "id": "string",
      "title": "string"
    }
  ]
}
401Missing authentication
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/auth/features" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/auth/locale

Set locale and redirect

Stores the selected locale in a cookie and redirects to a safe local path.

Parameters

NameInRequiredSchemaDescription
localequeryYesanyA locale code this tenant serves — one of the `servable` entries returned by `GET /api/translations/locales`. Codes are canonicalized (`de-AT` → `de`).
redirectqueryNoany—

Responses

200Success response
Content-Type: application/json
"string"
302Locale cookie set and request redirected
Content-Type: application/json
"string"
400Invalid locale
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/auth/locale?locale=string" \
  -H "Accept: application/json"
POST/auth/locale

Set locale

Stores the selected locale in a cookie and returns a JSON success response.

Request body (application/json)

{
  "locale": "string"
}

Responses

200Locale cookie set
Content-Type: application/json
{
  "ok": true
}
400Invalid locale or malformed request body
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/auth/locale" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"locale\": \"string\"
}"
POST/auth/login

Authenticate user credentials

Validates the submitted credentials and issues a bearer token cookie for subsequent API calls.

Request body (application/x-www-form-urlencoded)

email=user%40example.com&password=string

Responses

200Authentication succeeded
Content-Type: application/json
{
  "ok": true,
  "token": "string",
  "redirect": null
}
400Validation failed
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
401Invalid credentials
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
403User lacks required role
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
429Too many login attempts
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/auth/login" \
  -H "Accept: application/json" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "email=user%40example.com&password=string"
POST/auth/logout
Auth required

Invalidate session and redirect

Clears authentication cookies and redirects the browser to the login page.

Responses

201Success response
Content-Type: application/json
"string"
302Redirect to login after successful logout
Content-Type: text/html
string

Example

curl -X POST "http://108.165.128.56:3000/api/auth/logout" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/auth/profile
Auth required

Get current profile

Returns the email address, display name, and roles for the signed-in user. The display name is null when unset.

Responses

200Profile payload
Content-Type: application/json
{
  "email": "user@example.com",
  "name": null,
  "roles": [
    "string"
  ]
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
404User not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/auth/profile" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
PUT/auth/profile
Auth required

Update current profile

Updates the email address or password for the signed-in user.

Request body (application/json)

{}

Responses

200Profile updated
Content-Type: application/json
{
  "ok": true,
  "email": "user@example.com"
}
400Invalid payload
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X PUT "http://108.165.128.56:3000/api/auth/profile" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{}"
POST/auth/reset

Send reset email

Requests a password reset email for the given account. The endpoint always returns `ok: true` to avoid leaking account existence.

Request body (application/x-www-form-urlencoded)

email=user%40example.com

Responses

200Reset email dispatched (or ignored for unknown accounts)
Content-Type: application/json
{
  "ok": true
}
400Invalid request origin
Content-Type: application/json
{
  "error": "string"
}
429Too many password reset requests
Content-Type: application/json
{
  "error": "string"
}
500Password reset email origin is not configured
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/auth/reset" \
  -H "Accept: application/json" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "email=user%40example.com"
POST/auth/reset/confirm

Complete password reset

Validates the reset token and updates the user password.

Request body (application/x-www-form-urlencoded)

token=string&password=string

Responses

200Password reset succeeded
Content-Type: application/json
{
  "ok": true,
  "redirect": "string"
}
400Invalid token or payload
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
429Too many reset confirmation attempts
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/auth/reset/confirm" \
  -H "Accept: application/json" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "token=string&password=string"
POST/auth/reset/validate

Check whether a password reset token is still usable

Reports whether a reset token exists, is unused, and has not expired, so the reset page can render a terminal state instead of a form the token can never submit. The token is never consumed and the response never distinguishes unknown, used, and expired tokens.

Request body (application/x-www-form-urlencoded)

token=string

Responses

200Token state resolved
Content-Type: application/json
{
  "ok": true,
  "valid": true
}
429Too many token validation attempts
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/auth/reset/validate" \
  -H "Accept: application/json" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "token=string"
GET/auth/roles
Auth required

List roles

Returns available roles within the current tenant. Super administrators receive visibility across tenants.

Parameters

NameInRequiredSchemaDescription
idqueryNoany—
pagequeryNoany—
pageSizequeryNoany—
searchqueryNoany—
tenantIdqueryNoany—

Responses

200Role collection
Content-Type: application/json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "name": "string",
      "usersCount": 1,
      "tenantId": null,
      "tenantName": null,
      "updatedAt": null
    }
  ],
  "total": 1,
  "totalPages": 1
}

Example

curl -X GET "http://108.165.128.56:3000/api/auth/roles?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/auth/roles
Auth required

Create role

Creates a new role anchored to the caller's tenant. Non-superadmins cannot target another tenant; supplying a foreign `tenantId` is rejected.

Request body (application/json)

{
  "name": "string"
}

Responses

201Role created
Content-Type: application/json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
400Invalid payload
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/auth/roles" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"name\": \"string\"
}"
PUT/auth/roles
Auth required

Update role

Updates mutable fields on an existing role.

Request body (application/json)

{
  "id": "00000000-0000-4000-8000-000000000000"
}

Responses

200Role updated
Content-Type: application/json
{
  "ok": true
}
400Invalid payload
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
404Role not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X PUT "http://108.165.128.56:3000/api/auth/roles" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
DELETE/auth/roles
Auth required

Delete role

Deletes a role by identifier. Fails when users remain assigned.

Parameters

NameInRequiredSchemaDescription
idqueryYesanyRole identifier

Responses

200Role deleted
Content-Type: application/json
{
  "ok": true
}
400Role cannot be deleted
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
404Role not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/auth/roles?id=00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/auth/roles/acl
Auth required

Fetch role ACL

Returns the feature and organization assignments associated with a role within the current tenant.

Parameters

NameInRequiredSchemaDescription
roleIdqueryYesany—
tenantIdqueryNoany—

Responses

200Role ACL entry
Content-Type: application/json
{
  "isSuperAdmin": true,
  "features": [
    "string"
  ],
  "organizations": null,
  "updatedAt": null
}
400Invalid role id
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
404Role not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/auth/roles/acl?roleId=00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
PUT/auth/roles/acl
Auth required

Update role ACL

Replaces the feature list, super admin flag, and optional organization assignments for a role.

Request body (application/json)

{
  "roleId": "00000000-0000-4000-8000-000000000000",
  "organizations": null
}

Responses

200Role ACL updated
Content-Type: application/json
{
  "ok": true,
  "sanitized": true
}
400Invalid payload
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
403Insufficient privileges to modify ACL
Content-Type: application/json
{
  "error": "string"
}
404Role not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X PUT "http://108.165.128.56:3000/api/auth/roles/acl" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"roleId\": \"00000000-0000-4000-8000-000000000000\",
  \"organizations\": null
}"
GET/auth/session/refresh

Refresh auth cookie from session token (browser)

Exchanges an existing `session_token` cookie for a fresh JWT auth cookie and redirects the browser.

Parameters

NameInRequiredSchemaDescription
redirectqueryNoanyAbsolute or relative URL to redirect after refresh

Responses

200Success response
Content-Type: application/json
"string"
302Redirect to target location when session is valid
Content-Type: text/html
string

Example

curl -X GET "http://108.165.128.56:3000/api/auth/session/refresh" \
  -H "Accept: application/json"

API Keys

Showing 3 of 3 endpoints
GET/api_keys/keys
Auth required

List API keys

Returns paginated API keys visible to the current user, including per-key role assignments and organization context.

Parameters

NameInRequiredSchemaDescription
pagequeryNoany—
pageSizequeryNoany—
searchqueryNoany—

Responses

200Collection of API keys
Content-Type: application/json
{
  "items": [
    {
      "id": "string",
      "name": "string",
      "description": null,
      "keyPrefix": "string",
      "organizationId": null,
      "organizationName": null,
      "createdAt": "string",
      "lastUsedAt": null,
      "expiresAt": null,
      "roles": [
        {
          "id": "string",
          "name": null
        }
      ]
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
400Tenant context missing
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
403Forbidden by organization scope
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/api_keys/keys" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/api_keys/keys
Auth required

Create API key

Creates a new API key, returning the one-time secret value together with the generated key prefix and scope details.

Request body (application/json)

{
  "name": "string",
  "description": null,
  "tenantId": null,
  "organizationId": null,
  "roles": [],
  "expiresAt": null
}

Responses

201API key created successfully
Content-Type: application/json
{
  "id": "string",
  "name": "string",
  "keyPrefix": "string",
  "tenantId": null,
  "organizationId": null,
  "roles": [
    {
      "id": "string",
      "name": null
    }
  ]
}
400Invalid payload or missing tenant context
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
403Organization outside allowed scope
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/api_keys/keys" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"name\": \"string\",
  \"description\": null,
  \"tenantId\": null,
  \"organizationId\": null,
  \"roles\": [],
  \"expiresAt\": null
}"
DELETE/api_keys/keys
Auth required

Delete API key

Removes an API key by identifier. The key must belong to the current tenant and fall within the requester organization scope.

Parameters

NameInRequiredSchemaDescription
idqueryYesanyAPI key identifier to delete

Responses

200Key deleted successfully
Content-Type: application/json
{
  "success": true
}
400Missing or invalid identifier
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
403Organization outside allowed scope
Content-Type: application/json
{
  "error": "string"
}
404Key not found within scope
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/api_keys/keys?id=00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"

Directory (Tenants & Organizations)

Showing 2 of 2 endpoints
GET/directory/organizations/lookup

Public organization lookup by slug

Responses

200Success response
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/directory/organizations/lookup" \
  -H "Accept: application/json"
GET/directory/tenants/lookup

Public tenant lookup

Responses

200Success response
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/directory/tenants/lookup" \
  -H "Accept: application/json"

API Documentation

Showing 1 of 1 endpoints
GET/version

Deployed Open Mercato version

Responses

200Success response
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/version" \
  -H "Accept: application/json"

Audit & Action Logs

Showing 5 of 5 endpoints
GET/audit_logs/audit-logs/access
Auth required

Retrieve access logs

Fetches paginated access audit logs scoped to the authenticated user. Tenant administrators can optionally expand the search to other actors or organizations.

Parameters

NameInRequiredSchemaDescription
organizationIdqueryNoanyLimit results to a specific organization
actorUserIdqueryNoanyFilter by actor user id (tenant administrators only)
resourceKindqueryNoanyRestrict to a resource kind such as `order` or `product`
accessTypequeryNoanyAccess type filter, e.g. `read` or `export`
pagequeryNoanyPage number (default 1)
pageSizequeryNoanyPage size (default 50)
limitqueryNoanyExplicit maximum number of records when paginating manually
beforequeryNoanyReturn logs created before this ISO-8601 timestamp
afterqueryNoanyReturn logs created after this ISO-8601 timestamp

Responses

200Access logs returned successfully
Content-Type: application/json
{
  "items": [
    {
      "id": "string",
      "resourceKind": "string",
      "resourceId": "string",
      "accessType": "string",
      "actorUserId": null,
      "actorUserName": null,
      "tenantId": null,
      "tenantName": null,
      "organizationId": null,
      "organizationName": null,
      "fields": [
        "string"
      ],
      "context": null,
      "createdAt": "string"
    }
  ],
  "canViewTenant": true,
  "page": 1,
  "pageSize": 1,
  "total": 1,
  "totalPages": 1
}
400Invalid filters supplied
Content-Type: application/json
{
  "error": "string"
}
401Authentication required
Content-Type: application/json
{
  "error": "string"
}
403Caller has no resolved tenant scope and is not a superadmin
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/audit_logs/audit-logs/access" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/audit_logs/audit-logs/actions
Auth required

Fetch action logs

Returns recent action audit log entries. Tenant administrators can widen the scope to other actors or organizations, and callers can optionally restrict results to undoable actions.

Parameters

NameInRequiredSchemaDescription
organizationIdqueryNoanyLimit results to a specific organization
actorUserIdqueryNoanyFilter logs created by specific actor IDs (tenant administrators only). Accepts a single UUID or a comma-separated UUID list.
resourceKindqueryNoanyFilter by resource kind (e.g., "order", "product")
resourceIdqueryNoanyFilter by resource ID (UUID of the specific record)
actionTypequeryNoanyFilter by action type (`create`, `edit`, `delete`, `assign`). Accepts a single value or a comma-separated list.
fieldNamequeryNoanyFilter to entries where the given field changed. Accepts a single field name or a comma-separated list.
includeRelatedqueryNoanyWhen `true`, also returns changes to child entities linked via parentResourceKind/parentResourceId
includeTotalqueryNoanyWhen `true`, the response includes the filtered total count.
undoableOnlyqueryNoanyWhen `true`, only undoable actions are returned
limitqueryNoanyMaximum number of records to return (default 50, max 1000)
offsetqueryNoanyZero-based record offset for pagination (legacy — prefer page/pageSize)
pagequeryNoanyPage number (default 1)
pageSizequeryNoanyPage size (default 50, max 200)
sortFieldqueryNoanySort field: `createdAt`, `user`, `action`, `field`, or `source`.
sortDirqueryNoanySort direction: `asc` or `desc`.
beforequeryNoanyReturn actions created before this ISO-8601 timestamp
afterqueryNoanyReturn actions created after this ISO-8601 timestamp

Responses

200Action logs retrieved successfully
Content-Type: application/json
{
  "items": [
    {
      "id": "string",
      "commandId": "string",
      "actionLabel": null,
      "executionState": "done",
      "actorUserId": null,
      "actorUserName": null,
      "tenantId": null,
      "tenantName": null,
      "organizationId": null,
      "organizationName": null,
      "resourceKind": null,
      "resourceId": null,
      "parentResourceKind": null,
      "parentResourceId": null,
      "undoToken": null,
      "createdAt": "string",
      "updatedAt": "string",
      "snapshotBefore": null,
      "snapshotAfter": null,
      "changes": null,
      "context": null
    }
  ],
  "canViewTenant": true,
  "page": 1,
  "pageSize": 1,
  "total": 1,
  "totalPages": 1
}
400Invalid filter values
Content-Type: application/json
{
  "error": "string"
}
401Authentication required
Content-Type: application/json
{
  "error": "string"
}
403Caller has no resolved tenant scope and is not a superadmin
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/audit_logs/audit-logs/actions?includeRelated=false&includeTotal=false&undoableOnly=false" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/audit_logs/audit-logs/actions/export
Auth required

Export action logs as CSV

Returns a CSV attachment containing filtered action audit log entries. Tenant administrators can widen the scope to other actors or organizations.

Parameters

NameInRequiredSchemaDescription
organizationIdqueryNoanyLimit results to a specific organization
actorUserIdqueryNoanyFilter logs created by specific actor IDs (tenant administrators only). Accepts a single UUID or a comma-separated UUID list.
resourceKindqueryNoanyFilter by resource kind (e.g., "order", "product")
resourceIdqueryNoanyFilter by resource ID (UUID of the specific record)
actionTypequeryNoanyFilter by action type (`create`, `edit`, `delete`, `assign`). Accepts a single value or a comma-separated list.
fieldNamequeryNoanyFilter to entries where the given field changed. Accepts a single field name or a comma-separated list.
includeRelatedqueryNoanyWhen `true`, also returns changes to child entities linked via parentResourceKind/parentResourceId
undoableOnlyqueryNoanyWhen `true`, only undoable actions are returned
limitqueryNoanyMaximum number of records to export (default 1000, capped at 1000)
sortFieldqueryNoanySort field: `createdAt`, `user`, `action`, `field`, or `source`.
sortDirqueryNoanySort direction: `asc` or `desc`.
beforequeryNoanyReturn actions created before this ISO-8601 timestamp
afterqueryNoanyReturn actions created after this ISO-8601 timestamp

Responses

200CSV export generated successfully
Content-Type: application/json
{
  "file": "csv"
}
400Invalid filter values
Content-Type: application/json
{
  "error": "string"
}
401Authentication required
Content-Type: application/json
{
  "error": "string"
}
403Caller has no resolved tenant scope and is not a superadmin
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/audit_logs/audit-logs/actions/export?includeRelated=false&undoableOnly=false" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/audit_logs/audit-logs/actions/redo
Auth required

Redo by action log id

Redoes the latest undone command owned by the caller. Requires the action to still be eligible for redo within tenant and organization scope.

Request body (application/json)

{
  "logId": "string"
}

Responses

200Redo executed successfully
Content-Type: application/json
{
  "ok": true,
  "logId": null,
  "undoToken": null
}
400Log not eligible for redo
Content-Type: application/json
{
  "error": "string"
}
401Authentication required
Content-Type: application/json
{
  "error": "string"
}
403Redo blocked by scope checks
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/audit_logs/audit-logs/actions/redo" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"logId\": \"string\"
}"
POST/audit_logs/audit-logs/actions/undo
Auth required

Undo action by token

Replays the undo handler registered for a command. The provided undo token must match the latest undoable log entry accessible to the caller.

Request body (application/json)

{
  "undoToken": "string"
}

Responses

200Undo applied successfully
Content-Type: application/json
{
  "ok": true,
  "logId": "string"
}
400Invalid or unavailable undo token
Content-Type: application/json
{
  "error": "string"
}
401Authentication required
Content-Type: application/json
{
  "error": "string"
}
403Undo blocked by organization or tenant scope
Content-Type: application/json
{
  "error": "string"
}
422Undo deliberately blocked by a beforeUndo command interceptor. The interceptor chooses the status (any 4xx/5xx) and may replace the body.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/audit_logs/audit-logs/actions/undo" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"undoToken\": \"string\"
}"

Notifications

Showing 20 of 22 endpoints
GET/notifications
Auth required

List notifications

Returns a paginated collection of notifications.

Parameters

NameInRequiredSchemaDescription
statusqueryNoany—
typequeryNoany—
severityqueryNoany—
sourceEntityTypequeryNoany—
sourceEntityIdqueryNoany—
sincequeryNoany—
pagequeryNoany—
pageSizequeryNoany—
idsqueryNoanyComma-separated list of record UUIDs to filter by (max 200).

Responses

200Paginated notifications
Content-Type: application/json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "type": "string",
      "title": "string",
      "body": null,
      "titleKey": null,
      "bodyKey": null,
      "titleVariables": null,
      "bodyVariables": null,
      "icon": null,
      "severity": "string",
      "status": "string",
      "actions": [
        {
          "id": "string",
          "label": "string"
        }
      ],
      "sourceModule": null,
      "sourceEntityType": null,
      "sourceEntityId": null,
      "linkHref": null,
      "createdAt": "string",
      "readAt": null,
      "actionTaken": null
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
403Request could not be resolved to a tenant scope (code: tenant_scope_required)
Content-Type: application/json
{
  "error": "string",
  "code": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/notifications?page=1&pageSize=20" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/notifications
Auth required

Create notification

Creates a notification for a user.

Request body (application/json)

{
  "type": "string",
  "severity": "info",
  "recipientUserId": "00000000-0000-4000-8000-000000000000"
}

Responses

201Notification created
Content-Type: application/json
{
  "id": "00000000-0000-4000-8000-000000000000"
}

Example

curl -X POST "http://108.165.128.56:3000/api/notifications" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"type\": \"string\",
  \"severity\": \"info\",
  \"recipientUserId\": \"00000000-0000-4000-8000-000000000000\"
}"
POST/notifications/{id}/action
Auth required

POST /notifications/{id}/action

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

201Success response
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/notifications/:id/action" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
PUT/notifications/{id}/dismiss
Auth required

PUT /notifications/{id}/dismiss

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Success response
Content-Type: application/json
"string"

Example

curl -X PUT "http://108.165.128.56:3000/api/notifications/:id/dismiss" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
PUT/notifications/{id}/read
Auth required

PUT /notifications/{id}/read

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Success response
Content-Type: application/json
"string"

Example

curl -X PUT "http://108.165.128.56:3000/api/notifications/:id/read" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
PUT/notifications/{id}/restore
Auth required

PUT /notifications/{id}/restore

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Success response
Content-Type: application/json
"string"

Example

curl -X PUT "http://108.165.128.56:3000/api/notifications/:id/restore" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/notifications/admin/preferences
Auth required

GET /notifications/admin/preferences

Responses

200Success response
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/notifications/admin/preferences" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
PUT/notifications/admin/preferences
Auth required

PUT /notifications/admin/preferences

Responses

200Success response
Content-Type: application/json
"string"

Example

curl -X PUT "http://108.165.128.56:3000/api/notifications/admin/preferences" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/notifications/batch
Auth required

POST /notifications/batch

Responses

201Success response
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/notifications/batch" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/notifications/channels
Auth required

GET /notifications/channels

Responses

200Success response
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/notifications/channels" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/notifications/feature
Auth required

POST /notifications/feature

Responses

201Success response
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/notifications/feature" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
PUT/notifications/mark-all-read
Auth required

PUT /notifications/mark-all-read

Responses

200Success response
Content-Type: application/json
"string"

Example

curl -X PUT "http://108.165.128.56:3000/api/notifications/mark-all-read" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/notifications/preferences
Auth required

GET /notifications/preferences

Responses

200Success response
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/notifications/preferences" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
PUT/notifications/preferences
Auth required

PUT /notifications/preferences

Responses

200Success response
Content-Type: application/json
"string"

Example

curl -X PUT "http://108.165.128.56:3000/api/notifications/preferences" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/notifications/role
Auth required

POST /notifications/role

Responses

201Success response
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/notifications/role" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/notifications/settings
Auth required

GET /notifications/settings

Responses

200Success response
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/notifications/settings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/notifications/settings
Auth required

POST /notifications/settings

Responses

201Success response
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/notifications/settings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/notifications/types
Auth required

GET /notifications/types

Responses

200Success response
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/notifications/types" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
PATCH/notifications/types
Auth required

PATCH /notifications/types

Responses

200Success response
Content-Type: application/json
"string"

Example

curl -X PATCH "http://108.165.128.56:3000/api/notifications/types" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
PUT/notifications/types/{id}/channels/{channel}
Auth required

PUT /notifications/types/{id}/channels/{channel}

Parameters

NameInRequiredSchemaDescription
idpathYesany—
channelpathYesany—

Responses

200Success response
Content-Type: application/json
"string"

Example

curl -X PUT "http://108.165.128.56:3000/api/notifications/types/:id/channels/:channel" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"

Events

Showing 2 of 2 endpoints
GET/events
Auth required

List declared events

Returns every declared event, including its declared payloadSchema when the module (or the generated CRUD default) provides one. Filters: category, module, excludeTriggerExcluded (default true).

Responses

200Declared events
Content-Type: application/json
{
  "data": [
    {
      "id": "string",
      "label": "string"
    }
  ],
  "total": 1
}

Example

curl -X GET "http://108.165.128.56:3000/api/events" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/events/stream
Auth required

GET /events/stream

Responses

200Success response
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/events/stream" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"

Search

Showing 15 of 15 endpoints
GET/search/embeddings
Auth required

Get embeddings configuration

Returns current embedding provider and model configuration.

Responses

200Embeddings settings
Content-Type: application/json
{
  "settings": {
    "openaiConfigured": true,
    "autoIndexingEnabled": true,
    "autoIndexingLocked": true,
    "lockReason": null,
    "embeddingConfig": null,
    "configuredProviders": [
      "openai"
    ],
    "indexedDimension": null,
    "reindexRequired": true,
    "documentCount": null
  }
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/search/embeddings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/search/embeddings
Auth required

Update embeddings configuration

Updates the embedding provider and model settings.

Request body (application/json)

{}

Responses

200Updated settings
Content-Type: application/json
{
  "settings": {
    "openaiConfigured": true,
    "autoIndexingEnabled": true,
    "autoIndexingLocked": true,
    "lockReason": null,
    "embeddingConfig": null,
    "configuredProviders": [
      "openai"
    ],
    "indexedDimension": null,
    "reindexRequired": true,
    "documentCount": null
  }
}
400Invalid request
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
409Auto-indexing disabled via environment
Content-Type: application/json
{
  "error": "string"
}
500Update failed
Content-Type: application/json
{
  "error": "string"
}
503Configuration service unavailable
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/search/embeddings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{}"
POST/search/embeddings/reindex
Auth required

Trigger vector reindex

Starts a vector embedding reindex operation.

Request body (application/json)

{}

Responses

200Reindex result
Content-Type: application/json
{
  "ok": true
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
409Reindex already in progress
Content-Type: application/json
{
  "error": "string",
  "lock": {
    "type": "fulltext",
    "action": "string",
    "startedAt": "string",
    "elapsedMinutes": 1,
    "processedCount": null,
    "totalCount": null
  }
}
500Reindex failed
Content-Type: application/json
{
  "error": "string"
}
503Search indexer unavailable
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/search/embeddings/reindex" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{}"
POST/search/embeddings/reindex/cancel
Auth required

Cancel vector reindex

Cancels an in-progress vector reindex operation.

Responses

200Cancel result
Content-Type: application/json
{
  "ok": true,
  "jobsRemoved": 1
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/search/embeddings/reindex/cancel" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/search/index
Auth required

List vector index entries

Returns paginated list of entries in the vector search index.

Parameters

NameInRequiredSchemaDescription
entityIdqueryNoanyFilter by entity ID (e.g., "customers:customer_person_profile", "catalog:catalog_product")
limitqueryNoanyMaximum entries to return (default: 50, max: 200)
offsetqueryNoanyOffset for pagination (default: 0)

Responses

200Index entries
Content-Type: application/json
{
  "entries": [
    {
      "id": "string",
      "entityId": "string",
      "recordId": "string",
      "tenantId": "string",
      "organizationId": null
    }
  ],
  "limit": 1,
  "offset": 1
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
500Failed to fetch index
Content-Type: application/json
{
  "error": "string"
}
503Vector strategy unavailable
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/search/index" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
DELETE/search/index
Auth required

Purge vector index

Purges entries from the vector search index. Requires confirmAll=true when purging all entities.

Parameters

NameInRequiredSchemaDescription
entityIdqueryNoanySpecific entity ID to purge (e.g., "customers:customer_person_profile", "catalog:catalog_product")
confirmAllqueryNoanyRequired when purging all entities

Responses

200Purge result
Content-Type: application/json
{
  "ok": true
}
400Missing confirmAll parameter
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
500Purge failed
Content-Type: application/json
{
  "error": "string"
}
503Search indexer unavailable
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/search/index" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/search/reindex
Auth required

Trigger fulltext reindex

Starts a fulltext (Meilisearch) reindex operation. Can clear, recreate, or fully reindex.

Request body (application/json)

{}

Responses

200Reindex result
Content-Type: application/json
{
  "ok": true,
  "action": "clear",
  "entityId": null
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
409Reindex already in progress
Content-Type: application/json
{
  "error": "string",
  "lock": {
    "type": "fulltext",
    "action": "string",
    "startedAt": "string",
    "elapsedMinutes": 1,
    "processedCount": null,
    "totalCount": null
  }
}
500Reindex failed
Content-Type: application/json
{
  "error": "string"
}
503Search service unavailable
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/search/reindex" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{}"
POST/search/reindex/cancel
Auth required

Cancel fulltext reindex

Cancels an in-progress fulltext reindex operation.

Responses

200Cancel result
Content-Type: application/json
{
  "ok": true,
  "jobsRemoved": 1
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/search/reindex/cancel" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/search/search/global
Auth required

Global search (Cmd+K)

Performs a global search using saved tenant strategies. Does NOT accept strategies from URL.

Parameters

NameInRequiredSchemaDescription
qqueryYesanySearch query (required)
limitqueryNoanyMaximum results to return (default: 50, max: 100)
entityTypesqueryNoanyComma-separated entity types to filter results (e.g., "customers:customer_person_profile,catalog:catalog_product,sales:sales_order")

Responses

200Search results
Content-Type: application/json
{
  "results": [
    {
      "entityId": "string",
      "recordId": "string",
      "score": 1,
      "source": "fulltext"
    }
  ],
  "strategiesUsed": [
    "fulltext"
  ],
  "strategiesEnabled": [
    "fulltext"
  ],
  "timing": 1,
  "query": "string",
  "limit": 1
}
400Missing query parameter
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
500Search failed
Content-Type: application/json
{
  "error": "string"
}
503Search service unavailable
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/search/search/global?q=string" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/search/settings
Auth required

Get search settings and status

Returns search module configuration, available strategies, and reindex lock status.

Responses

200Search settings
Content-Type: application/json
{
  "settings": {
    "strategies": [
      {
        "id": "string",
        "name": "string",
        "priority": 1,
        "available": true
      }
    ],
    "fulltextConfigured": true,
    "fulltextStats": null,
    "vectorConfigured": true,
    "tokensEnabled": true,
    "defaultStrategies": [
      "string"
    ],
    "reindexLock": null,
    "fulltextReindexLock": null,
    "vectorReindexLock": null
  }
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/search/settings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/search/settings/fulltext
Auth required

Get fulltext search configuration

Returns Meilisearch configuration status and index statistics.

Responses

200Fulltext settings
Content-Type: application/json
{
  "driver": null,
  "configured": true,
  "envVars": {
    "MEILISEARCH_HOST": {
      "set": true,
      "hint": "string"
    },
    "MEILISEARCH_API_KEY": {
      "set": true,
      "hint": "string"
    }
  },
  "optionalEnvVars": {
    "MEILISEARCH_INDEX_PREFIX": {
      "set": true,
      "hint": "string"
    },
    "SEARCH_EXCLUDE_ENCRYPTED_FIELDS": {
      "set": true,
      "hint": "string"
    }
  }
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/search/settings/fulltext" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/search/settings/global-search
Auth required

Update global search strategies

Sets which strategies are enabled for Cmd+K global search.

Request body (application/json)

{
  "enabledStrategies": [
    "fulltext"
  ]
}

Responses

200Updated settings
Content-Type: application/json
{
  "ok": true,
  "enabledStrategies": [
    "fulltext"
  ]
}
400Invalid request
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
500Internal error
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/search/settings/global-search" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"enabledStrategies\": [
    \"fulltext\"
  ]
}"
GET/search/settings/vector-store
Auth required

Get vector store configuration

Returns vector store configuration status.

Responses

200Vector store settings
Content-Type: application/json
{
  "currentDriver": "pgvector",
  "configured": true,
  "drivers": [
    {
      "id": "pgvector",
      "name": "string",
      "configured": true,
      "implemented": true,
      "available": null,
      "unavailableReason": null,
      "envVars": [
        {
          "name": "string",
          "set": true,
          "hint": "string"
        }
      ]
    }
  ]
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/search/settings/vector-store" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"

Attachments

Showing 14 of 14 endpoints
GET/attachments
Auth required

List attachments for a record

Returns uploaded attachments for the given entity record, ordered by newest first.

Parameters

NameInRequiredSchemaDescription
entityIdqueryYesanyEntity identifier that owns the attachments
recordIdqueryYesanyRecord identifier within the entity
pagequeryNoany—
pageSizequeryNoany—

Responses

200Attachments found for the record
Content-Type: application/json
{
  "items": [
    {
      "id": "string",
      "url": "string",
      "fileName": "string",
      "fileSize": 1,
      "createdAt": "string",
      "mimeType": null,
      "content": null
    }
  ]
}
400Missing entity or record identifiers
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/attachments?entityId=string&recordId=string" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/attachments
Auth required

Upload attachment

Uploads a new attachment using multipart form-data and stores metadata for later retrieval.

Request body (multipart/form-data)

entityId=string
recordId=string
file=string

Responses

200Attachment stored successfully
Content-Type: application/json
{
  "ok": true,
  "item": {
    "id": "string",
    "url": "string",
    "fileName": "string",
    "fileSize": 1,
    "content": null
  }
}
400Payload validation error
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
403Attachment violates field constraints
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/attachments" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: multipart/form-data" \
  -d "{
  \"entityId\": \"string\",
  \"recordId\": \"string\",
  \"file\": \"string\"
}"
DELETE/attachments
Auth required

Delete attachment

Removes an uploaded attachment and deletes the stored asset.

Parameters

NameInRequiredSchemaDescription
idqueryYesany—

Responses

200Attachment deleted
Content-Type: application/json
{
  "ok": true
}
400Missing attachment identifier
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
404Attachment not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/attachments?id=00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/attachments/file/{id}

Download or serve attachment file

Returns the raw file content for an attachment. Path parameter: {id} - Attachment UUID. Query parameter: ?download=1 - Force file download with Content-Disposition header. Access control is enforced based on partition settings.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200File content with appropriate MIME type
Content-Type: application/json
"string"
400Missing attachment ID
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized - authentication required for private partitions
Content-Type: application/json
{
  "error": "string"
}
403Forbidden - insufficient permissions
Content-Type: application/json
{
  "error": "string"
}
404Attachment or file not found
Content-Type: application/json
{
  "error": "string"
}
500Partition misconfigured
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/attachments/file/:id" \
  -H "Accept: application/json"
GET/attachments/image/{id}/{slug}

Serve image with optional resizing

Returns an image attachment with optional on-the-fly resizing and cropping. Resized images are cached for performance. Only works with image MIME types. Path parameter: {id} - Attachment UUID. Query parameters: ?width=N (1-4000 pixels), ?height=N (1-4000 pixels), ?cropType=cover|contain (resize behavior).

Parameters

NameInRequiredSchemaDescription
idpathYesany—
slugpathNoany—

Responses

200Binary image content (Content-Type: image/jpeg, image/png, etc.)
Content-Type: application/json
"string"
400Invalid parameters, missing ID, or non-image attachment
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized - authentication required for private partitions
Content-Type: application/json
{
  "error": "string"
}
403Forbidden - insufficient permissions
Content-Type: application/json
{
  "error": "string"
}
404Image not found
Content-Type: application/json
{
  "error": "string"
}
500Partition misconfigured or image rendering failed
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/attachments/image/:id/:slug" \
  -H "Accept: application/json"
GET/attachments/library
Auth required

List attachments

Returns paginated list of attachments with optional filtering by search term, partition, and tags. Includes available tags and partitions.

Parameters

NameInRequiredSchemaDescription
pagequeryNoanyPage number for pagination
pageSizequeryNoanyNumber of items per page (max 100)
searchqueryNoanySearch by file name (case-insensitive)
partitionqueryNoanyFilter by partition code
tagsqueryNoanyFilter by tags (comma-separated)
sortFieldqueryNoanyField to sort by
sortDirqueryNoanySort direction

Responses

200Attachments list with pagination and metadata
Content-Type: application/json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "fileName": "string",
      "fileSize": 1,
      "mimeType": "string",
      "partitionCode": "string",
      "partitionTitle": null,
      "url": null,
      "createdAt": "string",
      "tags": [
        "string"
      ],
      "assignments": [],
      "content": null
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1,
  "availableTags": [
    "string"
  ],
  "partitions": [
    {
      "code": "string",
      "title": "string",
      "description": null,
      "isPublic": true
    }
  ]
}
400Invalid query parameters
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/attachments/library?page=1&pageSize=25" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/attachments/library/{id}
Auth required

Get attachment details

Returns complete details of an attachment including metadata, tags, assignments, and custom fields.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Attachment details
Content-Type: application/json
{
  "item": {
    "id": "00000000-0000-4000-8000-000000000000",
    "fileName": "string",
    "fileSize": 1,
    "mimeType": "string",
    "partitionCode": "string",
    "partitionTitle": null,
    "tags": [
      "string"
    ],
    "assignments": [],
    "content": null,
    "customFields": null
  }
}
400Invalid attachment ID
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
404Attachment not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/attachments/library/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
PATCH/attachments/library/{id}
Auth required

Update attachment metadata

Updates attachment tags, assignments, and custom fields. Emits CRUD side effects for indexing and events.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Request body (application/json)

{}

Responses

200Attachment updated successfully
Content-Type: application/json
{
  "ok": true
}
400Invalid payload or attachment ID
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
404Attachment not found
Content-Type: application/json
{
  "error": "string"
}
500Failed to save attributes
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X PATCH "http://108.165.128.56:3000/api/attachments/library/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{}"
DELETE/attachments/library/{id}
Auth required

Delete attachment

Permanently deletes an attachment file from storage and database. Emits CRUD side effects.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Attachment deleted successfully
Content-Type: application/json
{
  "ok": true
}
400Invalid attachment ID
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
404Attachment not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/attachments/library/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/attachments/partitions
Auth required

List all attachment partitions

Returns all configured attachment partitions with storage settings, OCR configuration, and access control settings.

Responses

200List of partitions
Content-Type: application/json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "code": "string",
      "title": "string",
      "description": null,
      "isPublic": true,
      "requiresOcr": true,
      "ocrModel": null,
      "configJson": null,
      "createdAt": null,
      "updatedAt": null,
      "envKey": "string"
    }
  ]
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/attachments/partitions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/attachments/partitions
Auth required

Create new partition

Creates a new attachment partition with specified storage and OCR settings. Requires unique partition code.

Request body (application/json)

{
  "code": "string",
  "title": "string",
  "description": null,
  "ocrModel": null,
  "storageDriver": "local",
  "configJson": null
}

Responses

201Partition created successfully
Content-Type: application/json
{
  "item": {
    "id": "00000000-0000-4000-8000-000000000000",
    "code": "string",
    "title": "string",
    "description": null,
    "isPublic": true,
    "requiresOcr": true,
    "ocrModel": null,
    "configJson": null,
    "createdAt": null,
    "updatedAt": null,
    "envKey": "string"
  }
}
400Invalid payload or partition code
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
403Partitions locked in demo mode
Content-Type: application/json
{
  "error": "string"
}
409Partition code already exists
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/attachments/partitions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"code\": \"string\",
  \"title\": \"string\",
  \"description\": null,
  \"ocrModel\": null,
  \"storageDriver\": \"local\",
  \"configJson\": null
}"
PUT/attachments/partitions
Auth required

Update partition

Updates an existing partition. Partition code cannot be changed. Title, description, OCR settings, and access control can be modified.

Request body (application/json)

{
  "code": "string",
  "title": "string",
  "description": null,
  "ocrModel": null,
  "storageDriver": "local",
  "configJson": null,
  "id": "00000000-0000-4000-8000-000000000000"
}

Responses

200Partition updated successfully
Content-Type: application/json
{
  "item": {
    "id": "00000000-0000-4000-8000-000000000000",
    "code": "string",
    "title": "string",
    "description": null,
    "isPublic": true,
    "requiresOcr": true,
    "ocrModel": null,
    "configJson": null,
    "createdAt": null,
    "updatedAt": null,
    "envKey": "string"
  }
}
400Invalid payload or code change attempt
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
403Partitions locked in demo mode
Content-Type: application/json
{
  "error": "string"
}
404Partition not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X PUT "http://108.165.128.56:3000/api/attachments/partitions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"code\": \"string\",
  \"title\": \"string\",
  \"description\": null,
  \"ocrModel\": null,
  \"storageDriver\": \"local\",
  \"configJson\": null,
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
DELETE/attachments/partitions
Auth required

Delete partition

Deletes a partition. Default partitions cannot be deleted. Partitions with existing attachments cannot be deleted.

Responses

200Partition deleted successfully
Content-Type: application/json
{
  "ok": true
}
400Invalid ID or default partition deletion attempt
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
403Partitions locked in demo mode
Content-Type: application/json
{
  "error": "string"
}
404Partition not found
Content-Type: application/json
{
  "error": "string"
}
409Partition in use
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/attachments/partitions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/attachments/transfer
Auth required

Transfer attachments to different record

Transfers one or more attachments from one record to another within the same entity type. Updates attachment assignments and metadata to reflect the new record.

Request body (application/json)

{
  "entityId": "string",
  "attachmentIds": [
    "00000000-0000-4000-8000-000000000000"
  ],
  "toRecordId": "string"
}

Responses

200Attachments transferred successfully
Content-Type: application/json
{
  "ok": true,
  "updated": 1
}
400Invalid payload
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
404Attachments not found
Content-Type: application/json
{
  "error": "string"
}
500Attachment model missing
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/attachments/transfer" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"entityId\": \"string\",
  \"attachmentIds\": [
    \"00000000-0000-4000-8000-000000000000\"
  ],
  \"toRecordId\": \"string\"
}"

Customer Relationship Management

Showing 2 of 2 endpoints
POST/customers/deals/bulk-update-owner
Auth required

Bulk reassign deal owner

Queues a background job that reassigns the listed deals to a new owner (or clears the owner when null).

Responses

201Success response
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/customers/deals/bulk-update-owner" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/customers/deals/bulk-update-stage
Auth required

Bulk update deal pipeline stage

Queues a background job that moves the listed deals to the same pipeline stage. Returns a progress job id to poll for completion.

Responses

201Success response
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/customers/deals/bulk-update-stage" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"

Messages

Showing 20 of 26 endpoints
GET/messages
Auth required

List messages

Parameters

NameInRequiredSchemaDescription
folderqueryNoany—
statusqueryNoany—
typequeryNoany—
visibilityqueryNoany—
sourceEntityTypequeryNoany—
sourceEntityIdqueryNoany—
externalEmailqueryNoany—
hasObjectsqueryNoany—
hasAttachmentsqueryNoany—
hasActionsqueryNoany—
senderIdqueryNoany—
searchqueryNoany—
sincequeryNoany—
pagequeryNoany—
pageSizequeryNoany—

Responses

200Message list
Content-Type: application/json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "type": "string",
      "visibility": null,
      "sourceEntityType": null,
      "sourceEntityId": null,
      "externalEmail": null,
      "externalName": null,
      "subject": "string",
      "bodyPreview": "string",
      "senderUserId": "00000000-0000-4000-8000-000000000000",
      "senderName": null,
      "senderEmail": null,
      "priority": "string",
      "status": "string",
      "hasObjects": true,
      "objectCount": 1,
      "hasAttachments": true,
      "attachmentCount": 1,
      "recipientCount": 1,
      "hasActions": true,
      "actionTaken": null,
      "sentAt": null,
      "readAt": null,
      "threadId": null
    }
  ],
  "page": 1,
  "pageSize": 1,
  "total": 1,
  "totalPages": 1
}

Example

curl -X GET "http://108.165.128.56:3000/api/messages?folder=inbox&page=1&pageSize=20" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/messages
Auth required

Compose a message

Request body (application/json)

{
  "type": "default",
  "visibility": null,
  "recipients": [],
  "subject": "",
  "body": "",
  "bodyFormat": "text",
  "priority": "normal",
  "sendViaEmail": false,
  "isDraft": false
}

Responses

201Message created
Content-Type: application/json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "threadId": null
}

Example

curl -X POST "http://108.165.128.56:3000/api/messages" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"type\": \"default\",
  \"visibility\": null,
  \"recipients\": [],
  \"subject\": \"\",
  \"body\": \"\",
  \"bodyFormat\": \"text\",
  \"priority\": \"normal\",
  \"sendViaEmail\": false,
  \"isDraft\": false
}"
GET/messages/{id}
Auth required

Get message detail

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Message detail with actor-visible thread items only
Content-Type: application/json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "updatedAt": null,
  "type": "string",
  "isDraft": true,
  "canEditDraft": true,
  "canArchive": true,
  "isArchived": true,
  "visibility": null,
  "sourceEntityType": null,
  "sourceEntityId": null,
  "externalEmail": null,
  "externalName": null,
  "typeDefinition": {
    "labelKey": "string",
    "icon": "string",
    "color": null,
    "allowReply": true,
    "allowForward": true,
    "ui": null
  },
  "threadId": null,
  "parentMessageId": null,
  "senderUserId": "00000000-0000-4000-8000-000000000000",
  "senderName": null,
  "senderEmail": null,
  "subject": "string",
  "body": "string",
  "bodyFormat": "text",
  "priority": "string",
  "sentAt": null,
  "actionData": null,
  "actionTaken": null,
  "actionTakenAt": null,
  "actionTakenByUserId": null,
  "recipients": [
    {
      "userId": "00000000-0000-4000-8000-000000000000",
      "type": "to",
      "status": "string",
      "readAt": null
    }
  ],
  "objects": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "entityModule": "string",
      "entityType": "string",
      "entityId": "00000000-0000-4000-8000-000000000000",
      "actionRequired": true,
      "actionType": null,
      "actionLabel": null,
      "snapshot": null,
      "preview": null
    }
  ],
  "thread": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "senderUserId": "00000000-0000-4000-8000-000000000000",
      "senderName": null,
      "senderEmail": null,
      "externalName": null,
      "externalEmail": null,
      "sourceEntityType": null,
      "body": "string",
      "sentAt": null
    }
  ],
  "isRead": true,
  "conversationArchived": true,
  "conversationAllUnread": true,
  "_channel": null,
  "_channelPayload": null,
  "_channelContact": null
}
403Access denied
Content-Type: application/json
{
  "error": "string"
}
404Message not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/messages/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
PATCH/messages/{id}
Auth required

Update draft message

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Request body (application/json)

{
  "visibility": null
}

Responses

200Draft updated
Content-Type: application/json
{
  "ok": true
}
403Access denied
Content-Type: application/json
{
  "error": "string"
}
404Message not found
Content-Type: application/json
{
  "error": "string"
}
409Only drafts can be edited, or the draft was modified concurrently (optimistic lock conflict)
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X PATCH "http://108.165.128.56:3000/api/messages/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"visibility\": null
}"
DELETE/messages/{id}
Auth required

Delete message for current sender/recipient context

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Message deleted
Content-Type: application/json
{
  "ok": true
}
403Access denied
Content-Type: application/json
{
  "error": "string"
}
404Message not found
Content-Type: application/json
{
  "error": "string"
}
409Message was modified concurrently (optimistic lock conflict)
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/messages/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/messages/{id}/actions/{actionId}
Auth required

Execute message action

Parameters

NameInRequiredSchemaDescription
idpathYesany—
actionIdpathYesany—

Request body (application/json)

"string"

Responses

200Action executed
Content-Type: application/json
{
  "ok": true,
  "actionId": "string"
}
403Access denied
Content-Type: application/json
"string"
404Action not found
Content-Type: application/json
"string"
409Action already taken, or the message was modified concurrently (optimistic lock conflict)
Content-Type: application/json
"string"
410Action expired
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/messages/:id/actions/:actionId" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
PUT/messages/{id}/archive
Auth required

Archive message

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Message archived
Content-Type: application/json
{
  "ok": true
}
403Access denied or sender-only message cannot be archived
Content-Type: application/json
{
  "error": "string"
}
404Message not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X PUT "http://108.165.128.56:3000/api/messages/:id/archive" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
DELETE/messages/{id}/archive
Auth required

Unarchive message

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Message unarchived
Content-Type: application/json
{
  "ok": true
}
403Access denied or sender-only message cannot be unarchived
Content-Type: application/json
{
  "error": "string"
}
404Message not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/messages/:id/archive" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/messages/{id}/attachments
Auth required

List message attachments

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Attachments
Content-Type: application/json
{
  "attachments": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "fileName": "string",
      "fileSize": 1,
      "mimeType": "string",
      "url": "string"
    }
  ]
}
403Access denied
Content-Type: application/json
{
  "error": "string"
}
404Message not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/messages/:id/attachments" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/messages/{id}/attachments
Auth required

Link attachments to draft message

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Request body (application/json)

{
  "attachmentIds": [
    "00000000-0000-4000-8000-000000000000"
  ]
}

Responses

200Attachments linked
Content-Type: application/json
{
  "ok": true
}
403Access denied
Content-Type: application/json
{
  "error": "string"
}
404Message not found
Content-Type: application/json
{
  "error": "string"
}
409Only draft messages can be edited
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/messages/:id/attachments" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"attachmentIds\": [
    \"00000000-0000-4000-8000-000000000000\"
  ]
}"
DELETE/messages/{id}/attachments
Auth required

Unlink attachments from draft message

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Request body (application/json)

{}

Responses

200Attachments unlinked
Content-Type: application/json
{
  "ok": true
}
403Access denied
Content-Type: application/json
{
  "error": "string"
}
404Message not found
Content-Type: application/json
{
  "error": "string"
}
409Only draft messages can be edited
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/messages/:id/attachments" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{}"
GET/messages/{id}/confirmation
Auth required

Read message confirmation status

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Confirmation status
Content-Type: application/json
{
  "messageId": "00000000-0000-4000-8000-000000000000",
  "confirmed": true,
  "confirmedAt": null,
  "confirmedByUserId": null
}
403Access denied
Content-Type: application/json
{
  "error": "string"
}
404Message not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/messages/:id/confirmation" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
DELETE/messages/{id}/conversation
Auth required

Delete conversation for current actor

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Conversation deleted
Content-Type: application/json
{
  "ok": true,
  "affectedCount": 1
}
403Access denied
Content-Type: application/json
{
  "error": "string"
}
404Message not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/messages/:id/conversation" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
PUT/messages/{id}/conversation/archive
Auth required

Archive conversation for current actor

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Conversation archived
Content-Type: application/json
{
  "ok": true,
  "affectedCount": 1
}
403Access denied
Content-Type: application/json
{
  "error": "string"
}
404Message not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X PUT "http://108.165.128.56:3000/api/messages/:id/conversation/archive" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
DELETE/messages/{id}/conversation/archive
Auth required

Unarchive conversation for current actor

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Conversation unarchived
Content-Type: application/json
{
  "ok": true,
  "affectedCount": 1
}
403Access denied
Content-Type: application/json
{
  "error": "string"
}
404Message not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/messages/:id/conversation/archive" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
PUT/messages/{id}/conversation/read
Auth required

Mark entire conversation as read for current actor

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Conversation marked read
Content-Type: application/json
{
  "ok": true,
  "affectedCount": 1
}
403Access denied
Content-Type: application/json
{
  "error": "string"
}
404Message not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X PUT "http://108.165.128.56:3000/api/messages/:id/conversation/read" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
DELETE/messages/{id}/conversation/read
Auth required

Mark entire conversation as unread for current actor

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Conversation marked unread
Content-Type: application/json
{
  "ok": true,
  "affectedCount": 1
}
403Access denied
Content-Type: application/json
{
  "error": "string"
}
404Message not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/messages/:id/conversation/read" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/messages/{id}/forward
Auth required

Forward a message and optionally include attachments from the forwarded conversation slice

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Request body (application/json)

{
  "recipients": [
    {
      "userId": "00000000-0000-4000-8000-000000000000",
      "type": "to"
    }
  ],
  "includeAttachments": true,
  "sendViaEmail": false
}

Responses

201Message forwarded
Content-Type: application/json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
403Access denied
Content-Type: application/json
"string"
404Message not found
Content-Type: application/json
"string"
409Forward not allowed for message type
Content-Type: application/json
"string"
413Forward body exceeds maximum length
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/messages/:id/forward" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"recipients\": [
    {
      \"userId\": \"00000000-0000-4000-8000-000000000000\",
      \"type\": \"to\"
    }
  ],
  \"includeAttachments\": true,
  \"sendViaEmail\": false
}"
GET/messages/{id}/forward-preview
Auth required

Get forward preview for a message

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Forward preview generated
Content-Type: application/json
{
  "subject": "string",
  "body": "string"
}
403Access denied
Content-Type: application/json
{
  "error": "string"
}
404Message not found
Content-Type: application/json
{
  "error": "string"
}
413Forward body exceeds maximum length
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/messages/:id/forward-preview" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
PUT/messages/{id}/read
Auth required

Mark message as read

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Message marked read
Content-Type: application/json
{
  "ok": true
}
403Access denied
Content-Type: application/json
{
  "error": "string"
}
404Message not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X PUT "http://108.165.128.56:3000/api/messages/:id/read" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"

Feature Toggles

Showing 12 of 12 endpoints
GET/feature_toggles/check/boolean
Auth required

Check if feature is enabled

Checks if a feature toggle is enabled for the current context.

Parameters

NameInRequiredSchemaDescription
identifierqueryYesanyFeature toggle identifier

Responses

200Feature status
Content-Type: application/json
{
  "enabled": true,
  "source": "override",
  "toggleId": "string",
  "identifier": "string",
  "tenantId": "string"
}
400Bad Request
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
404Tenant not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/feature_toggles/check/boolean?identifier=string" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/feature_toggles/check/json
Auth required

Get json config

Gets the json configuration for a feature toggle.

Parameters

NameInRequiredSchemaDescription
identifierqueryYesanyFeature toggle identifier

Responses

200Json config
Content-Type: application/json
{
  "valueType": "json",
  "source": "override",
  "toggleId": "string",
  "identifier": "string",
  "tenantId": "string"
}
400Bad Request
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
404Tenant not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/feature_toggles/check/json?identifier=string" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/feature_toggles/check/number
Auth required

Get number config

Gets the number configuration for a feature toggle.

Parameters

NameInRequiredSchemaDescription
identifierqueryYesanyFeature toggle identifier

Responses

200Number config
Content-Type: application/json
{
  "valueType": "number",
  "value": 1,
  "source": "override",
  "toggleId": "string",
  "identifier": "string",
  "tenantId": "string"
}
400Bad Request
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
404Tenant not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/feature_toggles/check/number?identifier=string" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/feature_toggles/check/string
Auth required

Get string config

Gets the string configuration for a feature toggle.

Parameters

NameInRequiredSchemaDescription
identifierqueryYesanyFeature toggle identifier

Responses

200String config
Content-Type: application/json
{
  "valueType": "string",
  "value": "string",
  "source": "override",
  "toggleId": "string",
  "identifier": "string",
  "tenantId": "string"
}
400Bad Request
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
404Tenant not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/feature_toggles/check/string?identifier=string" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/feature_toggles/global
Auth required

List global feature toggles

Returns all global feature toggles with filtering and pagination. Requires superadmin role.

Parameters

NameInRequiredSchemaDescription
pagequeryNoanyPage number for pagination
pageSizequeryNoanyNumber of items per page (max 200)
searchqueryNoanyCase-insensitive search across identifier, name, description, and category
typequeryNoanyFilter by toggle type (boolean, string, number, json)
categoryqueryNoanyFilter by category (case-insensitive partial match)
namequeryNoanyFilter by name (case-insensitive partial match)
identifierqueryNoanyFilter by identifier (case-insensitive partial match)
sortFieldqueryNoanyField to sort by
sortDirqueryNoanySort direction (ascending or descending)

Responses

200Feature toggles collection
Content-Type: application/json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "identifier": "string",
      "name": "string",
      "description": null,
      "category": null,
      "type": "boolean",
      "defaultValue": null,
      "createdAt": null,
      "updatedAt": null
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
400Invalid query parameters
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
403Forbidden - superadmin role required
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/feature_toggles/global?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/feature_toggles/global
Auth required

Create global feature toggle

Creates a new global feature toggle. Requires superadmin role.

Request body (application/json)

{
  "identifier": "string",
  "name": "string",
  "description": null,
  "category": null,
  "type": "boolean",
  "defaultValue": null
}

Responses

201Feature toggle created
Content-Type: application/json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
400Invalid payload
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
403Forbidden - superadmin role required
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/feature_toggles/global" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"identifier\": \"string\",
  \"name\": \"string\",
  \"description\": null,
  \"category\": null,
  \"type\": \"boolean\",
  \"defaultValue\": null
}"
PUT/feature_toggles/global
Auth required

Update global feature toggle

Updates an existing global feature toggle. Requires superadmin role.

Request body (application/json)

{
  "id": "00000000-0000-4000-8000-000000000000",
  "description": null,
  "category": null,
  "defaultValue": null
}

Responses

200Feature toggle updated
Content-Type: application/json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
400Invalid payload
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
403Forbidden - superadmin role required
Content-Type: application/json
{
  "error": "string"
}
404Feature toggle not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X PUT "http://108.165.128.56:3000/api/feature_toggles/global" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"description\": null,
  \"category\": null,
  \"defaultValue\": null
}"
DELETE/feature_toggles/global
Auth required

Delete global feature toggle

Soft deletes a global feature toggle by ID. Requires superadmin role.

Parameters

NameInRequiredSchemaDescription
idqueryYesanyFeature toggle identifier

Responses

200Feature toggle deleted
Content-Type: application/json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
400Invalid identifier
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
403Forbidden - superadmin role required
Content-Type: application/json
{
  "error": "string"
}
404Feature toggle not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/feature_toggles/global?id=00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/feature_toggles/global/{id}
Auth required

Fetch feature toggle by ID

Returns complete details of a feature toggle.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Feature toggle detail
Content-Type: application/json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "identifier": "string",
  "name": "string",
  "description": null,
  "category": null,
  "type": "boolean",
  "defaultValue": null,
  "createdAt": null,
  "updatedAt": null
}
400Invalid identifier
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
404Feature toggle not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/feature_toggles/global/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/feature_toggles/global/{id}/override
Auth required

Fetch feature toggle override

Returns feature toggle override.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Feature toggle overrides
Content-Type: application/json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "tenantName": "string",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "toggleType": "boolean",
  "updatedAt": null
}
400Invalid request
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
404Feature toggle not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/feature_toggles/global/:id/override" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/feature_toggles/overrides
Auth required

List overrides

Returns list of feature toggle overrides.

Parameters

NameInRequiredSchemaDescription
categoryqueryNoany—
namequeryNoany—
identifierqueryNoany—
sortFieldqueryNoany—
sortDirqueryNoany—
pagequeryNoany—
pageSizequeryNoany—

Responses

200List of overrides
Content-Type: application/json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "toggleId": "00000000-0000-4000-8000-000000000000",
      "tenantName": "string",
      "tenantId": "00000000-0000-4000-8000-000000000000",
      "identifier": "string",
      "name": "string",
      "category": "string",
      "isOverride": true
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1,
  "isSuperAdmin": true
}
400Invalid query parameters
Content-Type: application/json
{
  "error": "string"
}
401Authentication required
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/feature_toggles/overrides?page=1&pageSize=25" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
PUT/feature_toggles/overrides
Auth required

Change override state

Enable, disable or inherit a feature toggle for a specific tenant.

Request body (application/json)

{
  "toggleId": "00000000-0000-4000-8000-000000000000",
  "isOverride": true
}

Responses

200Override updated
Content-Type: application/json
{
  "ok": true,
  "overrideToggleId": null
}
400Validation failed
Content-Type: application/json
{
  "error": "string"
}
401Authentication required
Content-Type: application/json
{
  "error": "string"
}
404Not found
Content-Type: application/json
{
  "error": "string"
}
500Internal server error
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X PUT "http://108.165.128.56:3000/api/feature_toggles/overrides" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"toggleId\": \"00000000-0000-4000-8000-000000000000\",
  \"isOverride\": true
}"

Currencies

Showing 14 of 14 endpoints
GET/currencies/currencies
Auth required

List currencies

Returns a paginated collection of currencies scoped to the authenticated organization.

Parameters

NameInRequiredSchemaDescription
idqueryNoany—
pagequeryNoany—
pageSizequeryNoany—
searchqueryNoany—
sortFieldqueryNoany—
sortDirqueryNoany—
isBasequeryNoany—
isActivequeryNoany—
codequeryNoany—
idsqueryNoanyComma-separated list of record UUIDs to filter by (max 200).

Responses

200Paginated currencies
Content-Type: application/json
{
  "items": [
    {
      "id": "string",
      "code": "string",
      "name": "string",
      "symbol": null,
      "decimalPlaces": 1,
      "thousandsSeparator": null,
      "decimalSeparator": null,
      "isBase": true,
      "isActive": true,
      "createdAt": null,
      "updatedAt": null,
      "organizationId": "string",
      "tenantId": "string"
    }
  ],
  "total": 1,
  "totalPages": 1
}

Example

curl -X GET "http://108.165.128.56:3000/api/currencies/currencies?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/currencies/currencies
Auth required

Create currency

Creates a new currency.

Request body (application/json)

{
  "organizationId": "string",
  "tenantId": "string",
  "code": "string",
  "name": "string",
  "symbol": null,
  "thousandsSeparator": null,
  "decimalSeparator": null
}

Responses

201Currency created
Content-Type: application/json
{
  "id": null
}

Example

curl -X POST "http://108.165.128.56:3000/api/currencies/currencies" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"string\",
  \"tenantId\": \"string\",
  \"code\": \"string\",
  \"name\": \"string\",
  \"symbol\": null,
  \"thousandsSeparator\": null,
  \"decimalSeparator\": null
}"
PUT/currencies/currencies
Auth required

Update currency

Updates an existing currency by id.

Request body (application/json)

{
  "id": "string",
  "symbol": null,
  "thousandsSeparator": null,
  "decimalSeparator": null
}

Responses

200Currency updated
Content-Type: application/json
{
  "ok": true
}

Example

curl -X PUT "http://108.165.128.56:3000/api/currencies/currencies" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"string\",
  \"symbol\": null,
  \"thousandsSeparator\": null,
  \"decimalSeparator\": null
}"
DELETE/currencies/currencies
Auth required

Delete currency

Deletes a currency by id.

Request body (application/json)

{
  "id": "00000000-0000-4000-8000-000000000000"
}

Responses

200Currency deleted
Content-Type: application/json
{
  "ok": true
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/currencies/currencies" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
GET/currencies/currencies/options
Auth required

List currency options

Returns currencies formatted for select inputs.

Parameters

NameInRequiredSchemaDescription
qqueryNoany—
queryqueryNoany—
searchqueryNoany—
includeInactivequeryNoany—
limitqueryNoany—

Responses

200Option list
Content-Type: application/json
{
  "items": [
    {
      "value": "string",
      "label": "string"
    }
  ]
}
400Invalid query
Content-Type: application/json
{
  "items": []
}
401Unauthorized
Content-Type: application/json
{
  "items": []
}

Example

curl -X GET "http://108.165.128.56:3000/api/currencies/currencies/options?limit=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/currencies/exchange-rates
Auth required

List exchangerates

Returns a paginated collection of exchangerates scoped to the authenticated organization.

Parameters

NameInRequiredSchemaDescription
idqueryNoany—
pagequeryNoany—
pageSizequeryNoany—
sortFieldqueryNoany—
sortDirqueryNoany—
fromCurrencyCodequeryNoany—
toCurrencyCodequeryNoany—
isActivequeryNoany—
sourcequeryNoany—
typequeryNoany—
idsqueryNoanyComma-separated list of record UUIDs to filter by (max 200).

Responses

200Paginated exchangerates
Content-Type: application/json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "fromCurrencyCode": "string",
      "toCurrencyCode": "string",
      "rate": "string",
      "date": "string",
      "source": "string",
      "type": null,
      "isActive": true,
      "createdAt": null,
      "updatedAt": null,
      "organizationId": "00000000-0000-4000-8000-000000000000",
      "tenantId": "00000000-0000-4000-8000-000000000000"
    }
  ],
  "total": 1,
  "totalPages": 1
}

Example

curl -X GET "http://108.165.128.56:3000/api/currencies/exchange-rates?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/currencies/exchange-rates
Auth required

Create exchangerate

Creates a new exchange rate.

Request body (application/json)

{
  "organizationId": "string",
  "tenantId": "string",
  "fromCurrencyCode": "string",
  "toCurrencyCode": "string",
  "rate": "string",
  "type": null
}

Responses

201ExchangeRate created
Content-Type: application/json
{
  "id": null
}

Example

curl -X POST "http://108.165.128.56:3000/api/currencies/exchange-rates" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"string\",
  \"tenantId\": \"string\",
  \"fromCurrencyCode\": \"string\",
  \"toCurrencyCode\": \"string\",
  \"rate\": \"string\",
  \"type\": null
}"
PUT/currencies/exchange-rates
Auth required

Update exchangerate

Updates an existing exchange rate by id.

Request body (application/json)

{
  "id": "string",
  "type": null
}

Responses

200ExchangeRate updated
Content-Type: application/json
{
  "ok": true
}

Example

curl -X PUT "http://108.165.128.56:3000/api/currencies/exchange-rates" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"string\",
  \"type\": null
}"
DELETE/currencies/exchange-rates
Auth required

Delete exchangerate

Deletes an exchange rate by id.

Request body (application/json)

{
  "id": "00000000-0000-4000-8000-000000000000"
}

Responses

200ExchangeRate deleted
Content-Type: application/json
{
  "ok": true
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/currencies/exchange-rates" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
GET/currencies/fetch-configs
Auth required

List currency fetch configurations

Returns all currency fetch configurations scoped to the authenticated organization.

Responses

200A list of currency fetch configurations
Content-Type: application/json
{
  "configs": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "organizationId": "00000000-0000-4000-8000-000000000000",
      "tenantId": "00000000-0000-4000-8000-000000000000",
      "provider": "string",
      "isEnabled": true,
      "syncTime": null,
      "lastSyncAt": null,
      "lastSyncStatus": null,
      "lastSyncMessage": null,
      "lastSyncCount": null,
      "config": null,
      "createdAt": "string",
      "updatedAt": "string"
    }
  ]
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/currencies/fetch-configs" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/currencies/fetch-configs
Auth required

Create currency fetch configuration

Creates a new currency fetch configuration.

Request body (application/json)

{
  "provider": "NBP",
  "isEnabled": false,
  "syncTime": null,
  "config": null
}

Responses

201Currency fetch configuration created successfully
Content-Type: application/json
{
  "config": {
    "id": "00000000-0000-4000-8000-000000000000",
    "organizationId": "00000000-0000-4000-8000-000000000000",
    "tenantId": "00000000-0000-4000-8000-000000000000",
    "provider": "string",
    "isEnabled": true,
    "syncTime": null,
    "lastSyncAt": null,
    "lastSyncStatus": null,
    "lastSyncMessage": null,
    "lastSyncCount": null,
    "config": null,
    "createdAt": "string",
    "updatedAt": "string"
  }
}
400Bad request
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/currencies/fetch-configs" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"provider\": \"NBP\",
  \"isEnabled\": false,
  \"syncTime\": null,
  \"config\": null
}"
PUT/currencies/fetch-configs
Auth required

Update currency fetch configuration

Updates an existing currency fetch configuration by id.

Request body (application/json)

{
  "syncTime": null,
  "config": null,
  "id": "00000000-0000-4000-8000-000000000000"
}

Responses

200Currency fetch configuration updated successfully
Content-Type: application/json
{
  "config": {
    "id": "00000000-0000-4000-8000-000000000000",
    "organizationId": "00000000-0000-4000-8000-000000000000",
    "tenantId": "00000000-0000-4000-8000-000000000000",
    "provider": "string",
    "isEnabled": true,
    "syncTime": null,
    "lastSyncAt": null,
    "lastSyncStatus": null,
    "lastSyncMessage": null,
    "lastSyncCount": null,
    "config": null,
    "createdAt": "string",
    "updatedAt": "string"
  }
}
400Bad request
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X PUT "http://108.165.128.56:3000/api/currencies/fetch-configs" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"syncTime\": null,
  \"config\": null,
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
DELETE/currencies/fetch-configs
Auth required

Delete currency fetch configuration

Deletes a currency fetch configuration by id.

Parameters

NameInRequiredSchemaDescription
idqueryYesanyCurrency fetch configuration identifier to delete

Responses

200Currency fetch configuration deleted successfully
Content-Type: application/json
{
  "success": true
}
400Bad request
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/currencies/fetch-configs?id=00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/currencies/fetch-rates

Fetch currency rates

Fetches currency exchange rates from configured providers for a specific date.

Request body (application/json)

{}

Responses

200Currency rates fetched successfully
Content-Type: application/json
{
  "totalFetched": 1,
  "byProvider": {
    "key": {
      "count": 1
    }
  },
  "errors": [
    "string"
  ]
}
400Bad request
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
500Internal server error
Content-Type: application/json
{
  "totalFetched": 1,
  "byProvider": {
    "key": {
      "count": 1
    }
  },
  "errors": [
    "string"
  ]
}

Example

curl -X POST "http://108.165.128.56:3000/api/currencies/fetch-rates" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{}"

Communication Channels

Showing 1 of 1 endpoints
DELETE/communication_channels/channels/{id}
Auth required

DELETE /communication_channels/channels/{id}

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

204Success

No response body.

Example

curl -X DELETE "http://108.165.128.56:3000/api/communication_channels/channels/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"

AI Assistant

Showing 20 of 40 endpoints
GET/ai_assistant/ai/actions/{id}
Auth required

Fetch the current state of an AI pending action by id.

Returns the tenant-scoped {@link AiPendingAction} addressed by `:id`. Powers the chat UI reconnect/polling path: after a page reload or SSE reconnect the client carries the `pendingActionId` from an earlier `mutation-preview-card` UI part and calls this route to re-hydrate the card. Server-internal fields (`normalizedInput`, `createdByUserId`, `idempotencyKey`) are stripped by a whitelist serializer. Enforces tenant/org scoping via the repository.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Serialized pending action. Never includes normalizedInput, createdByUserId, or idempotencyKey.
Content-Type: application/json
"string"
401Unauthenticated caller.
Content-Type: application/json
"string"
403Caller lacks the `ai_assistant.view` feature.
Content-Type: application/json
"string"
404No pending action with the given id is accessible to the caller.
Content-Type: application/json
"string"
500Internal runtime failure.
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/ai_assistant/ai/actions/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/ai_assistant/ai/actions/{id}/cancel
Auth required

Cancel an AI pending action without executing the wrapped tool.

Flips a pending AI action from `pending` to `cancelled` and emits the `ai.action.cancelled` event. The tool handler is never invoked. Idempotent: a second call on a row already in `cancelled` status returns 200 with the current row without re-emitting the event. Rows whose `expiresAt` is in the past are flipped to `expired` and returned as 409 `expired` so the client can surface the TTL loss instead of silently masking it as a cancellation.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Cancellation complete (or idempotent replay); body includes the serialized pending action with status `cancelled`.
Content-Type: application/json
"string"
400Invalid cancel request body (unknown field, reason exceeds 500 chars, wrong type).
Content-Type: application/json
"string"
401Unauthenticated caller.
Content-Type: application/json
"string"
403Caller lacks `ai_assistant.view`.
Content-Type: application/json
"string"
404Pending action not found in the caller scope.
Content-Type: application/json
"string"
409Pending action is not in `pending` status (already confirmed/failed/executing) or has expired.
Content-Type: application/json
"string"
500Unexpected server failure during cancel.
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/ai_assistant/ai/actions/:id/cancel" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/ai_assistant/ai/actions/{id}/confirm
Auth required

Confirm an AI pending action, re-running every server-side check before execution.

Re-verifies the full contract from spec §9.4 (status, expiry, agent registration, required features, mutation policy, tool whitelist, attachment tenant scope, record version, and schema drift), flips the pending-action state machine to `executing`, invokes the wrapped tool handler, and persists `executionResult`. Idempotent: a second call on a row already in `confirmed` state returns the prior result without re-executing the handler.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Confirmation complete; body includes the serialized pending action and the mutation result.
Content-Type: application/json
"string"
401Unauthenticated caller.
Content-Type: application/json
"string"
403Caller lacks `ai_assistant.view`, a required agent feature, tool whitelist, or accesses attachments outside their tenant.
Content-Type: application/json
"string"
404Pending action or agent not found in the caller scope.
Content-Type: application/json
"string"
409Pending action is not in `pending` status or has expired.
Content-Type: application/json
"string"
412Record version changed between propose and confirm, or the input schema no longer accepts the stored payload.
Content-Type: application/json
"string"
500Unexpected server failure during confirm.
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/ai_assistant/ai/actions/:id/confirm" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/ai_assistant/ai/agents
Auth required

List registered AI agents, filtered by the caller's features.

Returns `{ agents: [...] }` — the subset of agents from `ai-agents.generated.ts` that the authenticated caller can invoke based on each agent's `requiredFeatures`. Mirrors the `meta.list_agents` tool handler so backoffice pages (e.g. the playground) can render an agent picker without going through the MCP tool transport.

Responses

200Accessible agent summaries.
Content-Type: application/json
"string"
401Unauthenticated caller.
Content-Type: application/json
"string"
500Internal failure while loading the agent registry.
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/ai_assistant/ai/agents" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/ai_assistant/ai/agents/{agentId}/loop-override
Auth required

Read the current loop-policy override for this agent, if any.

Returns `{ agentId, override }` where `override` is the agent-scoped loop-policy row from `ai_agent_runtime_overrides` (or `null`). Requires `ai_assistant.view`.

Parameters

NameInRequiredSchemaDescription
agentIdpathYesany—

Responses

200Loop override payload.
Content-Type: application/json
"string"
400Invalid agent id.
Content-Type: application/json
"string"
401Unauthenticated caller.
Content-Type: application/json
"string"
403Caller lacks `ai_assistant.view`.
Content-Type: application/json
"string"
404Unknown agent id.
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/ai_assistant/ai/agents/:agentId/loop-override" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
PUT/ai_assistant/ai/agents/{agentId}/loop-override
Auth required

Set (or replace) the tenant-scoped loop-policy override for this agent.

Body: loop columns. All fields are nullable/optional; `null` explicitly clears that axis. Validates `loopStopWhenJson` items and `loopActiveToolsJson` membership. Requires `ai_assistant.settings.manage`.

Parameters

NameInRequiredSchemaDescription
agentIdpathYesany—

Request body (application/json)

{
  "loopDisabled": null,
  "loopMaxSteps": null,
  "loopMaxToolCalls": null,
  "loopMaxWallClockMs": null,
  "loopMaxTokens": null,
  "loopStopWhenJson": null,
  "loopActiveToolsJson": null
}

Responses

200Override persisted.
Content-Type: application/json
"string"
400Invalid agent id or validation error.
Content-Type: application/json
"string"
401Unauthenticated caller.
Content-Type: application/json
"string"
403Caller lacks `ai_assistant.settings.manage`.
Content-Type: application/json
"string"
404Unknown agent id.
Content-Type: application/json
"string"

Example

curl -X PUT "http://108.165.128.56:3000/api/ai_assistant/ai/agents/:agentId/loop-override" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"loopDisabled\": null,
  \"loopMaxSteps\": null,
  \"loopMaxToolCalls\": null,
  \"loopMaxWallClockMs\": null,
  \"loopMaxTokens\": null,
  \"loopStopWhenJson\": null,
  \"loopActiveToolsJson\": null
}"
DELETE/ai_assistant/ai/agents/{agentId}/loop-override
Auth required

Remove the loop-policy columns from the agent-scoped runtime override row.

Nulls out all seven loop columns on the agent-scoped `ai_agent_runtime_overrides` row. Idempotent — returns 200 even when no override exists. Requires `ai_assistant.settings.manage`.

Parameters

NameInRequiredSchemaDescription
agentIdpathYesany—

Responses

200Loop override cleared (or already absent).
Content-Type: application/json
"string"
400Invalid agent id.
Content-Type: application/json
"string"
401Unauthenticated caller.
Content-Type: application/json
"string"
403Caller lacks `ai_assistant.settings.manage`.
Content-Type: application/json
"string"
404Unknown agent id.
Content-Type: application/json
"string"

Example

curl -X DELETE "http://108.165.128.56:3000/api/ai_assistant/ai/agents/:agentId/loop-override" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/ai_assistant/ai/agents/{agentId}/models
Auth required

Get the providers and curated models available for the chat-UI picker for this agent

Returns all configured providers with their curated model catalogs, filtered to providers that have an API key configured in the current environment. When the agent declares `allowRuntimeOverride: false`, the response reflects that constraint so the UI picker can hide itself. Includes the agent's resolved default provider/model so the picker can render a "(default)" badge next to the right entry. When a tenant-scoped lookup (the allowlist snapshot or the per-agent runtime override) cannot be loaded, the route still answers 200 with a partially resolved provider list and sets `degraded: true` plus a `degradedReason` code, so callers can tell a full entitlement list from a partial one. RBAC: requires the same features as the agent itself (typically `ai_assistant.view`).

Parameters

NameInRequiredSchemaDescription
agentIdpathYesany—

Responses

200Providers and curated models available for the agent picker. Empty `providers` array when `allowRuntimeOverride` is false. `degraded` is `false` and `degradedReason` is `null` on a fully resolved response; `degraded: true` with `degradedReason: "tenant_allowlist_unavailable"` means a tenant-scoped lookup failed, so `providers` may be missing the tenant allowlist and/or the per-agent override narrowing — one code covers the whole tenant-scoped block because no client can act differently per source. Clients SHOULD render the list but MUST NOT treat it as the tenant's authoritative entitlement (for example, do not prune a stored model selection against it).
Content-Type: application/json
"string"
401Unauthenticated.
Content-Type: application/json
"string"
403Caller lacks the agent's required features.
Content-Type: application/json
"string"
404Unknown agent id.
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/ai_assistant/ai/agents/:agentId/models" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/ai_assistant/ai/agents/{agentId}/mutation-policy
Auth required

Read the effective mutationPolicy for an agent — code-declared value plus any tenant override.

Returns `{ agentId, codeDeclared, override }` where `codeDeclared` is the agent's compiled-in `mutationPolicy` and `override` is the persisted tenant-scoped override (or `null`). Requires `ai_assistant.view`.

Parameters

NameInRequiredSchemaDescription
agentIdpathYesany—

Responses

200Effective mutationPolicy payload.
Content-Type: application/json
"string"
400Invalid agent id.
Content-Type: application/json
"string"
401Unauthenticated caller.
Content-Type: application/json
"string"
403Caller lacks `ai_assistant.view`.
Content-Type: application/json
"string"
404Unknown agent id.
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/ai_assistant/ai/agents/:agentId/mutation-policy" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/ai_assistant/ai/agents/{agentId}/mutation-policy
Auth required

Set (or replace) the tenant-scoped mutationPolicy override for this agent.

Body: `{ mutationPolicy: "read-only" | "confirm-required" | "destructive-confirm-required", notes? }`. The override MUST NOT escalate beyond the agent's code-declared policy. Escalation attempts are rejected with 400 + `code: "escalation_not_allowed"`. Requires `ai_assistant.settings.manage`.

Parameters

NameInRequiredSchemaDescription
agentIdpathYesany—

Request body (application/json)

{
  "mutationPolicy": "read-only"
}

Responses

200Override persisted.
Content-Type: application/json
"string"
400Invalid agent id, malformed body, or escalation attempt.
Content-Type: application/json
"string"
401Unauthenticated caller.
Content-Type: application/json
"string"
403Caller lacks `ai_assistant.settings.manage`.
Content-Type: application/json
"string"
404Unknown agent id.
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/ai_assistant/ai/agents/:agentId/mutation-policy" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"mutationPolicy\": \"read-only\"
}"
DELETE/ai_assistant/ai/agents/{agentId}/mutation-policy
Auth required

Remove the tenant-scoped mutationPolicy override for this agent.

Deletes the override row if it exists; subsequent calls fall back to the agent's code-declared policy. Idempotent — returns 200 even when no override exists. Requires `ai_assistant.settings.manage`.

Parameters

NameInRequiredSchemaDescription
agentIdpathYesany—

Responses

200Override cleared (or already absent).
Content-Type: application/json
"string"
400Invalid agent id.
Content-Type: application/json
"string"
401Unauthenticated caller.
Content-Type: application/json
"string"
403Caller lacks `ai_assistant.settings.manage`.
Content-Type: application/json
"string"
404Unknown agent id.
Content-Type: application/json
"string"

Example

curl -X DELETE "http://108.165.128.56:3000/api/ai_assistant/ai/agents/:agentId/mutation-policy" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/ai_assistant/ai/agents/{agentId}/prompt-override

Read the latest prompt-section override for an agent plus recent version history.

Returns `{ agentId, override, versions }` where `override` is the latest persisted row (or `null`) and `versions` is the newest-first history capped at 10 rows. Tenant-scoped; requires `ai_assistant.settings.manage`.

Parameters

NameInRequiredSchemaDescription
agentIdpathYesany—

Responses

200Latest override + recent version history.
Content-Type: application/json
"string"
400Invalid agent id.
Content-Type: application/json
"string"
401Unauthenticated caller.
Content-Type: application/json
"string"
403Caller lacks `ai_assistant.settings.manage`.
Content-Type: application/json
"string"
404Unknown agent id.
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/ai_assistant/ai/agents/:agentId/prompt-override" \
  -H "Accept: application/json"
POST/ai_assistant/ai/agents/{agentId}/prompt-override

Save a new prompt-section override version for the agent.

Persists an additive `{ sections: Record<sectionId, text>, notes? }` override, allocating the next monotonic version for `(tenant, org, agent)`. Reserved policy keys (`mutationPolicy`, `readOnly`, `allowedTools`, `acceptedMediaTypes`) are rejected with 400 / `reserved_key`. Requires `ai_assistant.settings.manage`.

Parameters

NameInRequiredSchemaDescription
agentIdpathYesany—

Request body (application/json)

{}

Responses

200Override persisted. Returns `{ ok: true, version, updatedAt }`.
Content-Type: application/json
"string"
400Invalid agent id, malformed body, or reserved policy key.
Content-Type: application/json
"string"
401Unauthenticated caller.
Content-Type: application/json
"string"
403Caller lacks `ai_assistant.settings.manage`.
Content-Type: application/json
"string"
404Unknown agent id.
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/ai_assistant/ai/agents/:agentId/prompt-override" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{}"
POST/ai_assistant/ai/chat
Auth required

Stream a chat turn for a registered AI agent

Dispatches a chat turn to the focused AI agent identified by `?agent=<module>.<agent>`. Enforces agent-level `requiredFeatures`, tool whitelisting, read-only / mutationPolicy, execution-mode compatibility, and attachment media-type policy. The streaming response body uses an AI SDK-compatible `text/event-stream` transport. Optional `?provider=`, `?model=`, and `?baseUrl=` query params let callers override the resolved provider/model/base-URL for this turn (Phase 4a). Provider must be registered and configured; baseUrl must match `AI_RUNTIME_BASEURL_ALLOWLIST` when set. Both are suppressed when the agent declares `allowRuntimeOverride: false`.

Parameters

NameInRequiredSchemaDescription
agentqueryYesany—
providerqueryNoany—
modelqueryNoany—
baseUrlqueryNoany—
loopBudgetqueryNoany—

Request body (application/json)

{
  "messages": [
    {
      "role": "user",
      "content": "string"
    }
  ]
}

Responses

200Streaming text/event-stream response compatible with AI SDK chat transports.
Content-Type: text/event-stream
string
400Invalid query param, malformed payload, or message count above the cap. Typed codes: `runtime_override_disabled` (agent has allowRuntimeOverride:false), `provider_unknown` (provider id not registered), `provider_not_configured` (provider registered but no API key in env), `baseurl_not_allowlisted` (baseUrl not in AI_RUNTIME_BASEURL_ALLOWLIST).
Content-Type: application/json
"string"
401Unauthenticated caller.
Content-Type: application/json
"string"
403Caller lacks agent-level or tool-level required features.
Content-Type: application/json
"string"
404Unknown agent id.
Content-Type: application/json
"string"
409Agent/tool/execution-mode policy violation.
Content-Type: application/json
"string"
500Internal runtime failure.
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/ai_assistant/ai/chat?agent=string" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"messages\": [
    {
      \"role\": \"user\",
      \"content\": \"string\"
    }
  ]
}"
GET/ai_assistant/ai/conversations
Auth required

List AI chat conversations visible to the caller.

Returns `{ items, nextCursor }` for the authenticated caller, ordered by `lastMessageAt` descending. View-only callers receive only their own conversations. Callers with `ai_assistant.conversations.manage` may list conversations across users in the same tenant/organization. The `agent` and `status` filters are optional; `cursor` is the ISO timestamp returned by a previous response.

Responses

200Caller-owned conversation summaries.
Content-Type: application/json
"string"
400Invalid query parameters.
Content-Type: application/json
"string"
401Unauthenticated caller.
Content-Type: application/json
"string"
403Caller lacks the `ai_assistant.view` feature.
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/ai_assistant/ai/conversations" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/ai_assistant/ai/conversations
Auth required

Idempotently create a new AI chat conversation.

If a non-deleted conversation already exists with the supplied `conversationId` for the authenticated caller in this tenant/org, returns the existing summary. Otherwise creates a fresh row and writes the owner-participant row in the same transaction.

Responses

200Existing conversation (idempotent path).
Content-Type: application/json
"string"
201Newly created conversation.
Content-Type: application/json
"string"
400Invalid request body.
Content-Type: application/json
"string"
401Unauthenticated caller.
Content-Type: application/json
"string"
403Caller lacks the `ai_assistant.view` feature.
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/ai_assistant/ai/conversations" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/ai_assistant/ai/conversations/{conversationId}
Auth required

Fetch a conversation summary and recent transcript.

Returns `{ conversation, messages, nextCursor }` for the supplied `conversationId`. View-only callers can load only their own conversations. Callers with `ai_assistant.conversations.manage` can load conversations across users in the same tenant/organization. Messages are ordered ascending by `createdAt`. The `before` cursor returns the next older page when paging back through long transcripts.

Parameters

NameInRequiredSchemaDescription
conversationIdpathYesany—

Responses

200Conversation transcript page for the authenticated owner.
Content-Type: application/json
"string"
400Invalid path or query parameters.
Content-Type: application/json
"string"
401Unauthenticated caller.
Content-Type: application/json
"string"
403Caller lacks the `ai_assistant.view` feature.
Content-Type: application/json
"string"
404No conversation accessible to the caller.
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/ai_assistant/ai/conversations/:conversationId" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
PATCH/ai_assistant/ai/conversations/{conversationId}
Auth required

Update an existing conversation.

Accepts a partial body containing any of `title`, `status`, `pageContext`. Setting `status` to `closed` archives the conversation while keeping its transcript intact. View-only callers can update only their own conversations; conversation managers can update conversations in the same tenant/organization.

Parameters

NameInRequiredSchemaDescription
conversationIdpathYesany—

Responses

200Updated conversation summary.
Content-Type: application/json
"string"
400Invalid request body.
Content-Type: application/json
"string"
401Unauthenticated caller.
Content-Type: application/json
"string"
403Caller lacks the `ai_assistant.view` feature.
Content-Type: application/json
"string"
404No conversation accessible to the caller.
Content-Type: application/json
"string"

Example

curl -X PATCH "http://108.165.128.56:3000/api/ai_assistant/ai/conversations/:conversationId" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
DELETE/ai_assistant/ai/conversations/{conversationId}
Auth required

Soft-delete a conversation and its messages.

View-only callers can delete only their own conversations. Callers with `ai_assistant.conversations.manage` can delete conversations in the same tenant/organization. Marks the conversation row and every undeleted message row with a `deleted_at` timestamp in one transaction. The transcript remains in the database for audit/restore until a future retention worker hard-deletes it.

Parameters

NameInRequiredSchemaDescription
conversationIdpathYesany—

Responses

200Soft-delete acknowledgment.
Content-Type: application/json
"string"
401Unauthenticated caller.
Content-Type: application/json
"string"
403Caller lacks the `ai_assistant.view` feature.
Content-Type: application/json
"string"
404No conversation accessible to the caller.
Content-Type: application/json
"string"

Example

curl -X DELETE "http://108.165.128.56:3000/api/ai_assistant/ai/conversations/:conversationId" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/ai_assistant/ai/conversations/{conversationId}/participants
Auth required

List active participants of a conversation.

Returns the list of active (non-revoked) participants for the conversation. Only the conversation owner or a caller with `ai_assistant.conversations.manage` can call this endpoint.

Parameters

NameInRequiredSchemaDescription
conversationIdpathYesany—

Responses

200List of active participants.
Content-Type: application/json
"string"
401Unauthenticated caller.
Content-Type: application/json
"string"
403Caller lacks required features.
Content-Type: application/json
"string"
404Conversation not found or not accessible.
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/ai_assistant/ai/conversations/:conversationId/participants" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"

Rich Methods CRM

Showing 15 of 15 endpoints
GET/richmethods_crm/campaigns
Auth required

List campaigns

Lists fundraising campaigns in scope, newest activity first, with raised totals recomputed from recorded donations.

Responses

200Campaign list.
Content-Type: application/json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "name": "string",
      "description": null,
      "status": "draft",
      "goalCents": null,
      "raisedCents": 1,
      "donationCount": 1,
      "startsAt": null,
      "endsAt": null,
      "updatedAt": "string"
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1
}
401Authentication required.
Content-Type: application/json
{
  "error": "string"
}
403Forbidden.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_crm/campaigns" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/richmethods_crm/campaigns
Auth required

Create a campaign

Creates a fundraising campaign record in scope. Donations are recorded against it through the donations API; no payment is processed. Idempotent by idempotencyKey.

Request body (application/json)

{
  "name": "string",
  "description": null,
  "goalCents": null,
  "startsAt": null,
  "endsAt": null,
  "idempotencyKey": "string"
}

Responses

201Campaign created.
Content-Type: application/json
{
  "item": {
    "id": "00000000-0000-4000-8000-000000000000",
    "name": "string",
    "description": null,
    "status": "draft",
    "goalCents": null,
    "raisedCents": 1,
    "donationCount": 1,
    "startsAt": null,
    "endsAt": null,
    "updatedAt": "string"
  },
  "duplicate": true
}
400Invalid request.
Content-Type: application/json
{
  "error": "string"
}
401Authentication required.
Content-Type: application/json
{
  "error": "string"
}
403Forbidden.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/richmethods_crm/campaigns" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"name\": \"string\",
  \"description\": null,
  \"goalCents\": null,
  \"startsAt\": null,
  \"endsAt\": null,
  \"idempotencyKey\": \"string\"
}"
GET/richmethods_crm/campaigns/{id}
Auth required

Read a campaign

Returns one campaign from scope with its recomputed raised totals.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Campaign.
Content-Type: application/json
{
  "item": {
    "id": "00000000-0000-4000-8000-000000000000",
    "name": "string",
    "description": null,
    "status": "draft",
    "goalCents": null,
    "raisedCents": 1,
    "donationCount": 1,
    "startsAt": null,
    "endsAt": null,
    "updatedAt": "string"
  }
}
401Authentication required.
Content-Type: application/json
{
  "error": "string"
}
403Forbidden.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_crm/campaigns/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
PUT/richmethods_crm/campaigns/{id}
Auth required

Update a campaign

Updates campaign fields under the updatedAt version the client last read; a stale version is a 409 conflict.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Request body (application/json)

{
  "description": null,
  "goalCents": null,
  "startsAt": null,
  "endsAt": null,
  "updatedAt": "string"
}

Responses

200Updated campaign.
Content-Type: application/json
{
  "item": {
    "id": "00000000-0000-4000-8000-000000000000",
    "name": "string",
    "description": null,
    "status": "draft",
    "goalCents": null,
    "raisedCents": 1,
    "donationCount": 1,
    "startsAt": null,
    "endsAt": null,
    "updatedAt": "string"
  }
}
404Campaign not found in scope.
Content-Type: application/json
{
  "error": "string"
}
409Version conflict.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X PUT "http://108.165.128.56:3000/api/richmethods_crm/campaigns/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"description\": null,
  \"goalCents\": null,
  \"startsAt\": null,
  \"endsAt\": null,
  \"updatedAt\": \"string\"
}"
DELETE/richmethods_crm/campaigns/{id}
Auth required

Delete a campaign

Soft-deletes the campaign under the updatedAt version the client last read. Donation records keep the campaign id as history.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Request body (application/json)

{
  "updatedAt": "string"
}

Responses

200Campaign deleted.
Content-Type: application/json
{
  "item": {
    "id": "00000000-0000-4000-8000-000000000000",
    "deleted": true
  }
}
404Campaign not found in scope.
Content-Type: application/json
{
  "error": "string"
}
409Version conflict.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/richmethods_crm/campaigns/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"updatedAt\": \"string\"
}"
GET/richmethods_crm/donations
Auth required

List donation records

Lists giving-history records in scope, most recent gift first. Filter by donorProfileId, campaignId, or status. Summaries exclude the encrypted reference and notes.

Responses

200Donation record list.
Content-Type: application/json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "donorProfileId": "00000000-0000-4000-8000-000000000000",
      "campaignId": null,
      "amountCents": 1,
      "currency": "string",
      "donatedAt": "string",
      "method": "card",
      "status": "recorded",
      "updatedAt": "string"
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1
}
401Authentication required.
Content-Type: application/json
{
  "error": "string"
}
403Forbidden.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_crm/donations" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/richmethods_crm/donations
Auth required

Record a donation

Records a donation in a donor's giving history and recomputes the donor and campaign rollups. This is a record only — no payment is processed. Idempotent by idempotencyKey.

Request body (application/json)

{
  "donorProfileId": "00000000-0000-4000-8000-000000000000",
  "campaignId": null,
  "amountCents": 1,
  "donatedAt": "string",
  "method": "card",
  "reference": null,
  "notes": null,
  "idempotencyKey": "string"
}

Responses

201Donation recorded.
Content-Type: application/json
{
  "item": {
    "id": "00000000-0000-4000-8000-000000000000",
    "donorProfileId": "00000000-0000-4000-8000-000000000000",
    "campaignId": null,
    "amountCents": 1,
    "currency": "string",
    "donatedAt": "string",
    "method": "card",
    "status": "recorded",
    "updatedAt": "string",
    "reference": null,
    "notes": null,
    "createdAt": "string"
  },
  "duplicate": true
}
400Invalid request, or donor/campaign not found in scope.
Content-Type: application/json
{
  "error": "string"
}
401Authentication required.
Content-Type: application/json
{
  "error": "string"
}
403Forbidden.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/richmethods_crm/donations" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"donorProfileId\": \"00000000-0000-4000-8000-000000000000\",
  \"campaignId\": null,
  \"amountCents\": 1,
  \"donatedAt\": \"string\",
  \"method\": \"card\",
  \"reference\": null,
  \"notes\": null,
  \"idempotencyKey\": \"string\"
}"
GET/richmethods_crm/donations/{id}
Auth required

Read a donation record

Returns one giving-history record from scope, including the decrypted reference and notes for authorized staff.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Donation record.
Content-Type: application/json
{
  "item": {
    "id": "00000000-0000-4000-8000-000000000000",
    "donorProfileId": "00000000-0000-4000-8000-000000000000",
    "campaignId": null,
    "amountCents": 1,
    "currency": "string",
    "donatedAt": "string",
    "method": "card",
    "status": "recorded",
    "updatedAt": "string",
    "reference": null,
    "notes": null,
    "createdAt": "string"
  }
}
401Authentication required.
Content-Type: application/json
{
  "error": "string"
}
403Forbidden.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_crm/donations/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
PUT/richmethods_crm/donations/{id}
Auth required

Update a donation record

Corrects a recorded donation under the updatedAt version the client last read; donor and campaign rollups are recomputed. A stale version is a 409 conflict.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Request body (application/json)

{
  "campaignId": null,
  "reference": null,
  "notes": null,
  "updatedAt": "string"
}

Responses

200Updated donation record.
Content-Type: application/json
{
  "item": {
    "id": "00000000-0000-4000-8000-000000000000",
    "donorProfileId": "00000000-0000-4000-8000-000000000000",
    "campaignId": null,
    "amountCents": 1,
    "currency": "string",
    "donatedAt": "string",
    "method": "card",
    "status": "recorded",
    "updatedAt": "string",
    "reference": null,
    "notes": null,
    "createdAt": "string"
  }
}
404Donation record not found in scope.
Content-Type: application/json
{
  "error": "string"
}
409Version conflict.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X PUT "http://108.165.128.56:3000/api/richmethods_crm/donations/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"campaignId\": null,
  \"reference\": null,
  \"notes\": null,
  \"updatedAt\": \"string\"
}"
DELETE/richmethods_crm/donations/{id}
Auth required

Delete a donation record

Soft-deletes the record under the updatedAt version the client last read and recomputes the rollups without it.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Request body (application/json)

{
  "updatedAt": "string"
}

Responses

200Donation record deleted.
Content-Type: application/json
{
  "item": {
    "id": "00000000-0000-4000-8000-000000000000",
    "deleted": true
  }
}
404Donation record not found in scope.
Content-Type: application/json
{
  "error": "string"
}
409Version conflict.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/richmethods_crm/donations/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"updatedAt\": \"string\"
}"
GET/richmethods_crm/donors
Auth required

List donor profiles

Lists donor profiles in the staff member's tenant/organization scope, newest activity first. Optional status and search filters; summaries exclude encrypted notes.

Responses

200Donor profile list.
Content-Type: application/json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "customerEntityId": "00000000-0000-4000-8000-000000000000",
      "customerKind": "string",
      "displayName": "string",
      "status": "prospect",
      "source": null,
      "firstGiftAt": null,
      "lastGiftAt": null,
      "lifetimeGivingCents": 1,
      "giftCount": 1,
      "updatedAt": "string"
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1
}
401Authentication required.
Content-Type: application/json
{
  "error": "string"
}
403Forbidden.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_crm/donors" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/richmethods_crm/donors
Auth required

Create a donor profile

Links a customers-module contact (the source of truth for the person or company) to a new donor profile in scope. Idempotent by idempotencyKey; a second create for the same customer returns the existing profile with duplicate: true. Sends nothing and processes no payment.

Request body (application/json)

{
  "customerEntityId": "00000000-0000-4000-8000-000000000000",
  "source": null,
  "notes": null,
  "idempotencyKey": "string"
}

Responses

201Donor profile created.
Content-Type: application/json
{
  "item": {
    "id": "00000000-0000-4000-8000-000000000000",
    "customerEntityId": "00000000-0000-4000-8000-000000000000",
    "customerKind": "string",
    "displayName": "string",
    "status": "prospect",
    "source": null,
    "firstGiftAt": null,
    "lastGiftAt": null,
    "lifetimeGivingCents": 1,
    "giftCount": 1,
    "updatedAt": "string",
    "notes": null,
    "createdAt": "string"
  },
  "duplicate": true
}
400Invalid request or unknown customer entity.
Content-Type: application/json
{
  "error": "string"
}
401Authentication required.
Content-Type: application/json
{
  "error": "string"
}
403Forbidden.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/richmethods_crm/donors" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"customerEntityId\": \"00000000-0000-4000-8000-000000000000\",
  \"source\": null,
  \"notes\": null,
  \"idempotencyKey\": \"string\"
}"
GET/richmethods_crm/donors/{id}
Auth required

Read a donor profile

Returns one donor profile from the staff member's scope, including decrypted notes for authorized staff.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Donor profile.
Content-Type: application/json
{
  "item": {
    "id": "00000000-0000-4000-8000-000000000000",
    "customerEntityId": "00000000-0000-4000-8000-000000000000",
    "customerKind": "string",
    "displayName": "string",
    "status": "prospect",
    "source": null,
    "firstGiftAt": null,
    "lastGiftAt": null,
    "lifetimeGivingCents": 1,
    "giftCount": 1,
    "updatedAt": "string",
    "notes": null,
    "createdAt": "string"
  }
}
401Authentication required.
Content-Type: application/json
{
  "error": "string"
}
403Forbidden.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_crm/donors/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
PUT/richmethods_crm/donors/{id}
Auth required

Update a donor profile

Updates status, source, or notes under the updatedAt version the client last read; a stale version is a 409 conflict.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Request body (application/json)

{
  "source": null,
  "notes": null,
  "updatedAt": "string"
}

Responses

200Updated donor profile.
Content-Type: application/json
{
  "item": {
    "id": "00000000-0000-4000-8000-000000000000",
    "customerEntityId": "00000000-0000-4000-8000-000000000000",
    "customerKind": "string",
    "displayName": "string",
    "status": "prospect",
    "source": null,
    "firstGiftAt": null,
    "lastGiftAt": null,
    "lifetimeGivingCents": 1,
    "giftCount": 1,
    "updatedAt": "string",
    "notes": null,
    "createdAt": "string"
  }
}
404Donor profile not found in scope.
Content-Type: application/json
{
  "error": "string"
}
409Version conflict.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X PUT "http://108.165.128.56:3000/api/richmethods_crm/donors/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"source\": null,
  \"notes\": null,
  \"updatedAt\": \"string\"
}"
DELETE/richmethods_crm/donors/{id}
Auth required

Delete a donor profile

Soft-deletes the donor profile under the updatedAt version the client last read. Donation records are kept as giving history.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Request body (application/json)

{
  "updatedAt": "string"
}

Responses

200Donor profile deleted.
Content-Type: application/json
{
  "item": {
    "id": "00000000-0000-4000-8000-000000000000",
    "deleted": true
  }
}
404Donor profile not found in scope.
Content-Type: application/json
{
  "error": "string"
}
409Version conflict.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/richmethods_crm/donors/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"updatedAt\": \"string\"
}"

Integrations

Showing 8 of 8 endpoints
GET/integrations
Auth required

List integrations

Returns a paginated collection of integrations.

Parameters

NameInRequiredSchemaDescription
qqueryNoany—
categoryqueryNoany—
bundleIdqueryNoany—
isEnabledqueryNoany—
healthStatusqueryNoany—
sortqueryNoany—
orderqueryNoany—
pagequeryNoany—
pageSizequeryNoany—
idsqueryNoanyComma-separated list of record UUIDs to filter by (max 200).

Responses

200Paginated integrations
Content-Type: application/json
{
  "items": [
    {
      "id": "string",
      "title": "string",
      "description": null,
      "category": null,
      "tags": [
        "string"
      ],
      "hub": null,
      "providerKey": null,
      "bundleId": null,
      "author": null,
      "company": null,
      "version": null,
      "hasCredentials": true,
      "isEnabled": true,
      "apiVersion": null,
      "healthStatus": "healthy",
      "lastHealthCheckedAt": null,
      "lastHealthLatencyMs": null,
      "enabledAt": null,
      "analytics": {
        "lastActivityAt": null,
        "totalCount": 1,
        "errorCount": 1,
        "errorRate": 1,
        "dailyCounts": [
          1
        ]
      }
    }
  ],
  "total": 1,
  "totalPages": 1,
  "bundles": [
    {
      "id": "string",
      "title": "string",
      "description": "string",
      "icon": null,
      "integrationCount": 1,
      "enabledCount": 1
    }
  ]
}

Example

curl -X GET "http://108.165.128.56:3000/api/integrations?order=asc&page=1&pageSize=100" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/integrations/{id}
Auth required

Get integration detail

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Success response
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/integrations/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/integrations/{id}/credentials
Auth required

Get or save integration credentials

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Success response
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/integrations/:id/credentials" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
PUT/integrations/{id}/credentials
Auth required

Get or save integration credentials

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Success response
Content-Type: application/json
"string"

Example

curl -X PUT "http://108.165.128.56:3000/api/integrations/:id/credentials" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/integrations/{id}/health
Auth required

Run health check for an integration

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

201Success response
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/integrations/:id/health" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
PUT/integrations/{id}/state
Auth required

Update integration state

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Success response
Content-Type: application/json
"string"

Example

curl -X PUT "http://108.165.128.56:3000/api/integrations/:id/state" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
PUT/integrations/{id}/version
Auth required

Change integration API version

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Success response
Content-Type: application/json
"string"

Example

curl -X PUT "http://108.165.128.56:3000/api/integrations/:id/version" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/integrations/logs
Auth required

List integration logs

Responses

200Success response
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/integrations/logs" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"

Business Rules

Showing 18 of 18 endpoints
POST/business_rules/execute
Auth required

Execute rules for given context

Manually executes applicable business rules for the specified entity type, event, and data. Supports dry-run mode to test rules without executing actions.

Request body (application/json)

{
  "entityType": "string",
  "dryRun": false
}

Responses

200Rules executed successfully
Content-Type: application/json
{
  "allowed": true,
  "executedRules": [
    {
      "ruleId": "string",
      "ruleName": "string",
      "conditionResult": true,
      "executionTime": 1
    }
  ],
  "totalExecutionTime": 1
}
400Invalid request payload
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
500Execution error
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/business_rules/execute" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"entityType\": \"string\",
  \"dryRun\": false
}"
POST/business_rules/execute/{ruleId}
Auth required

Execute a specific rule by its database UUID

Directly executes a specific business rule identified by its UUID, bypassing the normal entityType/eventType discovery mechanism. Useful for workflows and targeted rule execution.

Parameters

NameInRequiredSchemaDescription
ruleIdpathYesanyThe database UUID of the business rule to execute

Request body (application/json)

{
  "dryRun": false
}

Responses

200Rule executed successfully
Content-Type: application/json
{
  "success": true,
  "ruleId": "string",
  "ruleName": "string",
  "conditionResult": true,
  "actionsExecuted": null,
  "executionTime": 1
}
400Invalid request payload or rule ID
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
404Rule not found
Content-Type: application/json
{
  "error": "string"
}
500Execution error
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/business_rules/execute/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"dryRun\": false
}"
GET/business_rules/logs
Auth required

List rule execution logs

Returns rule execution history for the current tenant and organization with filtering and pagination. Useful for audit trails and debugging.

Parameters

NameInRequiredSchemaDescription
idqueryNoany—
pagequeryNoany—
pageSizequeryNoany—
ruleIdqueryNoany—
entityIdqueryNoany—
entityTypequeryNoany—
executionResultqueryNoany—
executedByqueryNoany—
executedAtFromqueryNoany—
executedAtToqueryNoany—
sortFieldqueryNoany—
sortDirqueryNoany—

Responses

200Rule execution logs collection
Content-Type: application/json
{
  "items": [
    {
      "id": "string",
      "ruleId": "string",
      "ruleName": "string",
      "ruleType": "string",
      "entityId": "00000000-0000-4000-8000-000000000000",
      "entityType": "string",
      "executionResult": "SUCCESS",
      "inputContext": null,
      "outputContext": null,
      "errorMessage": null,
      "executionTimeMs": 1,
      "executedAt": "string",
      "tenantId": "00000000-0000-4000-8000-000000000000",
      "organizationId": null,
      "executedBy": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
400Invalid query parameters
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/business_rules/logs?page=1&pageSize=50&sortDir=desc" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/business_rules/logs/{id}
Auth required

Get execution log detail

Returns detailed information about a specific rule execution, including full context and results.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Log entry details
Content-Type: application/json
{
  "id": "string",
  "rule": {
    "id": "00000000-0000-4000-8000-000000000000",
    "ruleId": "string",
    "ruleName": "string",
    "ruleType": "string",
    "entityType": "string"
  },
  "entityId": "00000000-0000-4000-8000-000000000000",
  "entityType": "string",
  "executionResult": "SUCCESS",
  "inputContext": null,
  "outputContext": null,
  "errorMessage": null,
  "executionTimeMs": 1,
  "executedAt": "string",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "organizationId": null,
  "executedBy": null
}
400Invalid log id
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
404Log entry not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/business_rules/logs/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/business_rules/openmercato-call-options
Auth required

List OpenMercato call action options

Returns executable Open Mercato API endpoint options and safe API key profile metadata for business-rule actions.

Responses

200OpenMercato call options
Content-Type: application/json
{
  "endpoints": [
    {
      "id": "string",
      "path": "string",
      "method": "GET",
      "label": "string",
      "summary": null,
      "operationId": null
    }
  ],
  "apiKeys": [
    {
      "id": "string",
      "name": "string",
      "keyPrefix": "string",
      "organizationId": null,
      "organizationName": null,
      "roles": [
        {
          "id": "string",
          "name": null
        }
      ]
    }
  ]
}
400Tenant context missing
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
403Missing required features
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/business_rules/openmercato-call-options" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/business_rules/rules
Auth required

List business rules

Returns business rules for the current tenant and organization with filtering and pagination.

Parameters

NameInRequiredSchemaDescription
idqueryNoany—
pagequeryNoany—
pageSizequeryNoany—
searchqueryNoany—
ruleIdqueryNoany—
ruleTypequeryNoany—
entityTypequeryNoany—
eventTypequeryNoany—
enabledqueryNoany—
ruleCategoryqueryNoany—
sortFieldqueryNoany—
sortDirqueryNoany—

Responses

200Business rules collection
Content-Type: application/json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "ruleId": "string",
      "ruleName": "string",
      "description": null,
      "ruleType": "GUARD",
      "ruleCategory": null,
      "entityType": "string",
      "eventType": null,
      "enabled": true,
      "priority": 1,
      "version": 1,
      "effectiveFrom": null,
      "effectiveTo": null,
      "tenantId": "00000000-0000-4000-8000-000000000000",
      "organizationId": "00000000-0000-4000-8000-000000000000",
      "createdAt": "string",
      "updatedAt": "string"
    }
  ],
  "total": 1,
  "totalPages": 1
}
400Invalid query parameters
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/business_rules/rules?page=1&pageSize=50&sortDir=desc" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/business_rules/rules
Auth required

Create business rule

Creates a new business rule for the current tenant and organization.

Request body (application/json)

{
  "ruleId": "string",
  "ruleName": "string",
  "description": null,
  "ruleType": "GUARD",
  "ruleCategory": null,
  "entityType": "string",
  "eventType": null,
  "enabled": true,
  "priority": 100,
  "version": 1,
  "effectiveFrom": null,
  "effectiveTo": null,
  "tenantId": "string",
  "organizationId": "string",
  "createdBy": null,
  "conditionExpression": null,
  "successActions": null,
  "failureActions": null
}

Responses

201Business rule created
Content-Type: application/json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
400Invalid payload
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/business_rules/rules" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"ruleId\": \"string\",
  \"ruleName\": \"string\",
  \"description\": null,
  \"ruleType\": \"GUARD\",
  \"ruleCategory\": null,
  \"entityType\": \"string\",
  \"eventType\": null,
  \"enabled\": true,
  \"priority\": 100,
  \"version\": 1,
  \"effectiveFrom\": null,
  \"effectiveTo\": null,
  \"tenantId\": \"string\",
  \"organizationId\": \"string\",
  \"createdBy\": null,
  \"conditionExpression\": null,
  \"successActions\": null,
  \"failureActions\": null
}"
PUT/business_rules/rules
Auth required

Update business rule

Updates an existing business rule.

Request body (application/json)

{
  "description": null,
  "ruleCategory": null,
  "eventType": null,
  "enabled": true,
  "priority": 100,
  "version": 1,
  "effectiveFrom": null,
  "effectiveTo": null,
  "conditionExpression": null,
  "successActions": null,
  "failureActions": null,
  "id": "string"
}

Responses

200Business rule updated
Content-Type: application/json
{
  "ok": true
}
400Invalid payload
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
404Business rule not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X PUT "http://108.165.128.56:3000/api/business_rules/rules" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"description\": null,
  \"ruleCategory\": null,
  \"eventType\": null,
  \"enabled\": true,
  \"priority\": 100,
  \"version\": 1,
  \"effectiveFrom\": null,
  \"effectiveTo\": null,
  \"conditionExpression\": null,
  \"successActions\": null,
  \"failureActions\": null,
  \"id\": \"string\"
}"
DELETE/business_rules/rules
Auth required

Delete business rule

Soft deletes a business rule by identifier.

Parameters

NameInRequiredSchemaDescription
idqueryYesanyBusiness rule identifier

Responses

200Business rule deleted
Content-Type: application/json
{
  "ok": true
}
400Invalid identifier
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
404Business rule not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/business_rules/rules?id=00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/business_rules/rules/{id}
Auth required

Fetch business rule by ID

Returns complete details of a business rule including conditions and actions.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Business rule detail
Content-Type: application/json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "ruleId": "string",
  "ruleName": "string",
  "description": null,
  "ruleType": "GUARD",
  "ruleCategory": null,
  "entityType": "string",
  "eventType": null,
  "successActions": null,
  "failureActions": null,
  "enabled": true,
  "priority": 1,
  "version": 1,
  "effectiveFrom": null,
  "effectiveTo": null,
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "createdBy": null,
  "updatedBy": null,
  "createdAt": "string",
  "updatedAt": "string"
}
400Invalid identifier
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
404Business rule not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/business_rules/rules/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/business_rules/sets
Auth required

List rule sets

Returns rule sets for the current tenant and organization with filtering and pagination.

Parameters

NameInRequiredSchemaDescription
idqueryNoany—
pagequeryNoany—
pageSizequeryNoany—
searchqueryNoany—
setIdqueryNoany—
enabledqueryNoany—
sortFieldqueryNoany—
sortDirqueryNoany—

Responses

200Rule sets collection
Content-Type: application/json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "setId": "string",
      "setName": "string",
      "description": null,
      "enabled": true,
      "tenantId": "00000000-0000-4000-8000-000000000000",
      "organizationId": "00000000-0000-4000-8000-000000000000",
      "createdBy": null,
      "updatedBy": null,
      "createdAt": "string",
      "updatedAt": "string"
    }
  ],
  "total": 1,
  "totalPages": 1
}
400Invalid query parameters
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/business_rules/sets?page=1&pageSize=50&sortDir=asc" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/business_rules/sets
Auth required

Create rule set

Creates a new rule set for organizing business rules.

Request body (application/json)

{
  "setId": "string",
  "setName": "string",
  "description": null,
  "enabled": true,
  "tenantId": "string",
  "organizationId": "string",
  "createdBy": null
}

Responses

201Rule set created
Content-Type: application/json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
400Invalid payload
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/business_rules/sets" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"setId\": \"string\",
  \"setName\": \"string\",
  \"description\": null,
  \"enabled\": true,
  \"tenantId\": \"string\",
  \"organizationId\": \"string\",
  \"createdBy\": null
}"
PUT/business_rules/sets
Auth required

Update rule set

Updates an existing rule set.

Request body (application/json)

{
  "description": null,
  "enabled": true,
  "id": "string"
}

Responses

200Rule set updated
Content-Type: application/json
{
  "ok": true
}
400Invalid payload
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
404Rule set not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X PUT "http://108.165.128.56:3000/api/business_rules/sets" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"description\": null,
  \"enabled\": true,
  \"id\": \"string\"
}"
DELETE/business_rules/sets
Auth required

Delete rule set

Soft deletes a rule set by identifier.

Parameters

NameInRequiredSchemaDescription
idqueryYesanyRule set identifier

Responses

200Rule set deleted
Content-Type: application/json
{
  "ok": true
}
400Invalid identifier
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
404Rule set not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/business_rules/sets?id=00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/business_rules/sets/{id}
Auth required

Get rule set detail

Returns detailed information about a specific rule set, including all member rules.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Rule set details
Content-Type: application/json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "setId": "string",
  "setName": "string",
  "description": null,
  "enabled": true,
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "createdBy": null,
  "updatedBy": null,
  "createdAt": "string",
  "updatedAt": "string",
  "members": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "ruleId": "00000000-0000-4000-8000-000000000000",
      "ruleName": "string",
      "ruleType": "string",
      "sequence": 1,
      "enabled": true
    }
  ]
}
400Invalid rule set id
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
404Rule set not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/business_rules/sets/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/business_rules/sets/{id}/members
Auth required

Add rule to set

Adds a business rule to a rule set with specified sequence and enabled state.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Request body (application/json)

{
  "ruleId": "00000000-0000-4000-8000-000000000000",
  "sequence": 0,
  "enabled": true
}

Responses

201Member added
Content-Type: application/json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
400Invalid payload
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
404Rule set or rule not found
Content-Type: application/json
{
  "error": "string"
}
409Rule already in set
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/business_rules/sets/:id/members" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"ruleId\": \"00000000-0000-4000-8000-000000000000\",
  \"sequence\": 0,
  \"enabled\": true
}"
PUT/business_rules/sets/{id}/members
Auth required

Update set member

Updates sequence or enabled state of a rule set member.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Request body (application/json)

{
  "memberId": "00000000-0000-4000-8000-000000000000"
}

Responses

200Member updated
Content-Type: application/json
{
  "ok": true
}
400Invalid payload
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
404Member not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X PUT "http://108.165.128.56:3000/api/business_rules/sets/:id/members" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"memberId\": \"00000000-0000-4000-8000-000000000000\"
}"
DELETE/business_rules/sets/{id}/members
Auth required

Remove rule from set

Removes a business rule from a rule set (hard delete).

Parameters

NameInRequiredSchemaDescription
idpathYesany—
memberIdqueryYesanyMember identifier

Responses

200Member removed
Content-Type: application/json
{
  "ok": true
}
400Invalid identifier
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
404Member not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/business_rules/sets/:id/members?memberId=00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"

Webhooks

Showing 20 of 24 endpoints
GET/webhooks
Auth required

List webhooks

Returns paginated webhooks for the current tenant and organization.

Parameters

NameInRequiredSchemaDescription
pagequeryNoany—
pageSizequeryNoany—
searchqueryNoany—
isActivequeryNoany—

Responses

200Webhook collection
Content-Type: application/json
{
  "items": [
    {
      "id": "string",
      "name": "string",
      "description": null,
      "url": "string",
      "subscribedEvents": [
        "string"
      ],
      "httpMethod": "string",
      "isActive": true,
      "deliveryStrategy": "string",
      "maxRetries": 1,
      "consecutiveFailures": 1,
      "lastSuccessAt": null,
      "lastFailureAt": null,
      "createdAt": "string",
      "updatedAt": "string"
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
400Tenant context missing
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/webhooks" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/webhooks
Auth required

Create webhook

Creates a new webhook endpoint. A signing secret (whsec_ prefixed) is auto-generated and returned once.

Request body (application/json)

{
  "name": "string",
  "description": null,
  "url": "https://example.com/resource",
  "subscribedEvents": [
    "string"
  ],
  "httpMethod": "POST",
  "customHeaders": null,
  "deliveryStrategy": "http",
  "strategyConfig": null,
  "maxRetries": 10,
  "timeoutMs": 15000,
  "rateLimitPerMinute": 0,
  "autoDisableThreshold": 100,
  "integrationId": null
}

Responses

201Webhook created
Content-Type: application/json
{
  "id": "string",
  "name": "string",
  "url": "string",
  "secret": "string",
  "subscribedEvents": [
    "string"
  ],
  "isActive": true
}
400Invalid payload
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/webhooks" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"name\": \"string\",
  \"description\": null,
  \"url\": \"https://example.com/resource\",
  \"subscribedEvents\": [
    \"string\"
  ],
  \"httpMethod\": \"POST\",
  \"customHeaders\": null,
  \"deliveryStrategy\": \"http\",
  \"strategyConfig\": null,
  \"maxRetries\": 10,
  \"timeoutMs\": 15000,
  \"rateLimitPerMinute\": 0,
  \"autoDisableThreshold\": 100,
  \"integrationId\": null
}"
GET/webhooks/{id}
Auth required

Get webhook

Returns webhook configuration, masked secret metadata, and delivery settings.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Webhook detail
Content-Type: application/json
{
  "id": "string",
  "name": "string",
  "description": null,
  "url": "string",
  "subscribedEvents": [
    "string"
  ],
  "httpMethod": "string",
  "isActive": true,
  "deliveryStrategy": "string",
  "maxRetries": 1,
  "consecutiveFailures": 1,
  "lastSuccessAt": null,
  "lastFailureAt": null,
  "createdAt": "string",
  "updatedAt": "string",
  "customHeaders": null,
  "strategyConfig": null,
  "timeoutMs": 1,
  "rateLimitPerMinute": 1,
  "autoDisableThreshold": 1,
  "integrationId": null,
  "maskedSecret": "string",
  "previousSecretSetAt": null
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
404Webhook not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/webhooks/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
PUT/webhooks/{id}
Auth required

Update webhook

Updates a single webhook configuration.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Request body (application/json)

{
  "description": null,
  "httpMethod": "POST",
  "customHeaders": null,
  "deliveryStrategy": "http",
  "strategyConfig": null,
  "maxRetries": 10,
  "timeoutMs": 15000,
  "rateLimitPerMinute": 0,
  "autoDisableThreshold": 100,
  "integrationId": null
}

Responses

200Webhook updated
Content-Type: application/json
{
  "id": "string",
  "name": "string",
  "description": null,
  "url": "string",
  "subscribedEvents": [
    "string"
  ],
  "httpMethod": "string",
  "isActive": true,
  "deliveryStrategy": "string",
  "maxRetries": 1,
  "consecutiveFailures": 1,
  "lastSuccessAt": null,
  "lastFailureAt": null,
  "createdAt": "string",
  "updatedAt": "string",
  "customHeaders": null,
  "strategyConfig": null,
  "timeoutMs": 1,
  "rateLimitPerMinute": 1,
  "autoDisableThreshold": 1,
  "integrationId": null,
  "maskedSecret": "string",
  "previousSecretSetAt": null
}
400Invalid payload
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
404Webhook not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X PUT "http://108.165.128.56:3000/api/webhooks/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"description\": null,
  \"httpMethod\": \"POST\",
  \"customHeaders\": null,
  \"deliveryStrategy\": \"http\",
  \"strategyConfig\": null,
  \"maxRetries\": 10,
  \"timeoutMs\": 15000,
  \"rateLimitPerMinute\": 0,
  \"autoDisableThreshold\": 100,
  \"integrationId\": null
}"
DELETE/webhooks/{id}
Auth required

Delete webhook

Soft-deletes a webhook endpoint.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Webhook deleted
Content-Type: application/json
{
  "success": true
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
404Webhook not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/webhooks/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/webhooks/{id}/rotate-secret
Auth required

Rotate secret

Returns the new secret once. Store it immediately; future reads only expose a masked value.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Secret rotated
Content-Type: application/json
{
  "success": true,
  "secret": "string",
  "previousSecretSetAt": null
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
404Webhook not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/webhooks/00000000-0000-4000-8000-000000000000/rotate-secret" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/webhooks/{id}/test
Auth required

Test webhook

Creates a synthetic event payload and delivers it immediately without using the queue.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Request body (application/json)

{}

Responses

200Test delivery result
Content-Type: application/json
{
  "success": true,
  "delivery": {
    "id": "string",
    "webhookId": "string",
    "eventType": "string",
    "messageId": "string",
    "status": "string",
    "responseStatus": null,
    "errorMessage": null,
    "attemptNumber": 1,
    "maxAttempts": 1,
    "targetUrl": "string",
    "durationMs": null,
    "enqueuedAt": "string",
    "lastAttemptAt": null,
    "deliveredAt": null,
    "createdAt": "string",
    "payload": {},
    "responseBody": null,
    "responseHeaders": null,
    "nextRetryAt": null,
    "updatedAt": "string"
  }
}
400Invalid request payload
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
404Webhook not found
Content-Type: application/json
{
  "error": "string"
}
409Webhook integration disabled
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/webhooks/00000000-0000-4000-8000-000000000000/test" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{}"
GET/webhooks/deliveries
Auth required

List delivery logs

Returns paginated webhook delivery attempts with filtering by webhook, event type, and status.

Parameters

NameInRequiredSchemaDescription
pagequeryNoany—
pageSizequeryNoany—
webhookIdqueryNoany—
eventTypequeryNoany—
statusqueryNoany—

Responses

200Delivery log collection
Content-Type: application/json
{
  "items": [
    {
      "id": "string",
      "webhookId": "string",
      "webhookName": null,
      "eventType": "string",
      "messageId": "string",
      "status": "string",
      "responseStatus": null,
      "errorMessage": null,
      "attemptNumber": 1,
      "maxAttempts": 1,
      "targetUrl": "string",
      "durationMs": null,
      "enqueuedAt": "string",
      "lastAttemptAt": null,
      "deliveredAt": null,
      "createdAt": "string"
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
400Tenant context missing
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/webhooks/deliveries?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/webhooks/deliveries/{id}
Auth required

Get delivery

Returns a single delivery attempt by ID.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Delivery detail
Content-Type: application/json
{
  "id": "string",
  "webhookId": "string",
  "eventType": "string",
  "messageId": "string",
  "status": "string",
  "responseStatus": null,
  "errorMessage": null,
  "attemptNumber": 1,
  "maxAttempts": 1,
  "targetUrl": "string",
  "durationMs": null,
  "enqueuedAt": "string",
  "lastAttemptAt": null,
  "deliveredAt": null,
  "createdAt": "string",
  "payload": {},
  "responseBody": null,
  "responseHeaders": null,
  "nextRetryAt": null,
  "updatedAt": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
404Delivery not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/webhooks/deliveries/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/webhooks/deliveries/{id}/retry
Auth required

Retry delivery

Resets retry scheduling fields and enqueues the delivery again.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Delivery re-enqueued
Content-Type: application/json
{
  "success": true,
  "delivery": {
    "id": "string",
    "webhookId": "string",
    "eventType": "string",
    "messageId": "string",
    "status": "string",
    "responseStatus": null,
    "errorMessage": null,
    "attemptNumber": 1,
    "maxAttempts": 1,
    "targetUrl": "string",
    "durationMs": null,
    "enqueuedAt": "string",
    "lastAttemptAt": null,
    "deliveredAt": null,
    "createdAt": "string",
    "payload": {},
    "responseBody": null,
    "responseHeaders": null,
    "nextRetryAt": null,
    "updatedAt": "string"
  }
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
404Delivery not found
Content-Type: application/json
{
  "error": "string"
}
409Webhook integration disabled
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/webhooks/deliveries/00000000-0000-4000-8000-000000000000/retry" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/webhooks/events
Auth required

List webhook events

Returns all declared non-webhook events, sorted by event id.

Responses

200Available events
Content-Type: application/json
{
  "data": [
    {
      "id": "string",
      "label": "string"
    }
  ],
  "total": 1
}

Example

curl -X GET "http://108.165.128.56:3000/api/webhooks/events" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/webhooks/inbound/{endpointId}

Receive inbound webhook

The endpoint id resolves to a registered webhook source first (module-level handler dispatch), otherwise to a legacy adapter provider key.

Parameters

NameInRequiredSchemaDescription
endpointIdpathYesany—

Responses

200Inbound webhook accepted
Content-Type: application/json
{
  "ok": true
}
400Verification failed or stale webhook timestamp
Content-Type: application/json
{
  "error": "string"
}
401Signature verification failed (source flow)
Content-Type: application/json
{
  "error": "string"
}
404Endpoint not found
Content-Type: application/json
{
  "error": "string"
}
413Webhook payload too large
Content-Type: application/json
{
  "error": "string"
}
429Rate limit exceeded
Content-Type: application/json
{
  "error": "string"
}
503Webhook integration disabled
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/webhooks/inbound/string" \
  -H "Accept: application/json"
GET/webhooks/webhook-deliveries
Auth required

List delivery logs

Returns paginated webhook delivery attempts with filtering by webhook, event type, and status.

Parameters

NameInRequiredSchemaDescription
pagequeryNoany—
pageSizequeryNoany—
webhookIdqueryNoany—
eventTypequeryNoany—
statusqueryNoany—

Responses

200Delivery log collection
Content-Type: application/json
{
  "items": [
    {
      "id": "string",
      "webhookId": "string",
      "webhookName": null,
      "eventType": "string",
      "messageId": "string",
      "status": "string",
      "responseStatus": null,
      "errorMessage": null,
      "attemptNumber": 1,
      "maxAttempts": 1,
      "targetUrl": "string",
      "durationMs": null,
      "enqueuedAt": "string",
      "lastAttemptAt": null,
      "deliveredAt": null,
      "createdAt": "string"
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
400Tenant context missing
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/webhooks/webhook-deliveries?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/webhooks/webhook-deliveries/{id}
Auth required

Get delivery

Returns a single delivery attempt by ID.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Delivery detail
Content-Type: application/json
{
  "id": "string",
  "webhookId": "string",
  "eventType": "string",
  "messageId": "string",
  "status": "string",
  "responseStatus": null,
  "errorMessage": null,
  "attemptNumber": 1,
  "maxAttempts": 1,
  "targetUrl": "string",
  "durationMs": null,
  "enqueuedAt": "string",
  "lastAttemptAt": null,
  "deliveredAt": null,
  "createdAt": "string",
  "payload": {},
  "responseBody": null,
  "responseHeaders": null,
  "nextRetryAt": null,
  "updatedAt": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
404Delivery not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/webhooks/webhook-deliveries/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/webhooks/webhook-deliveries/{id}/retry
Auth required

Retry delivery

Resets retry scheduling fields and enqueues the delivery again.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Delivery re-enqueued
Content-Type: application/json
{
  "success": true,
  "delivery": {
    "id": "string",
    "webhookId": "string",
    "eventType": "string",
    "messageId": "string",
    "status": "string",
    "responseStatus": null,
    "errorMessage": null,
    "attemptNumber": 1,
    "maxAttempts": 1,
    "targetUrl": "string",
    "durationMs": null,
    "enqueuedAt": "string",
    "lastAttemptAt": null,
    "deliveredAt": null,
    "createdAt": "string",
    "payload": {},
    "responseBody": null,
    "responseHeaders": null,
    "nextRetryAt": null,
    "updatedAt": "string"
  }
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
404Delivery not found
Content-Type: application/json
{
  "error": "string"
}
409Webhook integration disabled
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/webhooks/webhook-deliveries/00000000-0000-4000-8000-000000000000/retry" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/webhooks/webhooks
Auth required

List webhooks

Returns paginated webhooks for the current tenant and organization.

Parameters

NameInRequiredSchemaDescription
pagequeryNoany—
pageSizequeryNoany—
searchqueryNoany—
isActivequeryNoany—

Responses

200Webhook collection
Content-Type: application/json
{
  "items": [
    {
      "id": "string",
      "name": "string",
      "description": null,
      "url": "string",
      "subscribedEvents": [
        "string"
      ],
      "httpMethod": "string",
      "isActive": true,
      "deliveryStrategy": "string",
      "maxRetries": 1,
      "consecutiveFailures": 1,
      "lastSuccessAt": null,
      "lastFailureAt": null,
      "createdAt": "string",
      "updatedAt": "string"
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
400Tenant context missing
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/webhooks/webhooks" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/webhooks/webhooks
Auth required

Create webhook

Creates a new webhook endpoint. A signing secret (whsec_ prefixed) is auto-generated and returned once.

Request body (application/json)

{
  "name": "string",
  "description": null,
  "url": "https://example.com/resource",
  "subscribedEvents": [
    "string"
  ],
  "httpMethod": "POST",
  "customHeaders": null,
  "deliveryStrategy": "http",
  "strategyConfig": null,
  "maxRetries": 10,
  "timeoutMs": 15000,
  "rateLimitPerMinute": 0,
  "autoDisableThreshold": 100,
  "integrationId": null
}

Responses

201Webhook created
Content-Type: application/json
{
  "id": "string",
  "name": "string",
  "url": "string",
  "secret": "string",
  "subscribedEvents": [
    "string"
  ],
  "isActive": true
}
400Invalid payload
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/webhooks/webhooks" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"name\": \"string\",
  \"description\": null,
  \"url\": \"https://example.com/resource\",
  \"subscribedEvents\": [
    \"string\"
  ],
  \"httpMethod\": \"POST\",
  \"customHeaders\": null,
  \"deliveryStrategy\": \"http\",
  \"strategyConfig\": null,
  \"maxRetries\": 10,
  \"timeoutMs\": 15000,
  \"rateLimitPerMinute\": 0,
  \"autoDisableThreshold\": 100,
  \"integrationId\": null
}"
PUT/webhooks/webhooks
Auth required

Update webhook

Updates an existing webhook configuration.

Request body (application/json)

{
  "description": null,
  "httpMethod": "POST",
  "customHeaders": null,
  "deliveryStrategy": "http",
  "strategyConfig": null,
  "maxRetries": 10,
  "timeoutMs": 15000,
  "rateLimitPerMinute": 0,
  "autoDisableThreshold": 100,
  "integrationId": null
}

Responses

200Webhook updated
Content-Type: application/json
{
  "id": "string",
  "name": "string",
  "description": null,
  "url": "string",
  "subscribedEvents": [
    "string"
  ],
  "httpMethod": "string",
  "isActive": true,
  "deliveryStrategy": "string",
  "maxRetries": 1,
  "consecutiveFailures": 1,
  "lastSuccessAt": null,
  "lastFailureAt": null,
  "createdAt": "string",
  "updatedAt": "string",
  "customHeaders": null,
  "strategyConfig": null,
  "timeoutMs": 1,
  "rateLimitPerMinute": 1,
  "autoDisableThreshold": 1,
  "integrationId": null
}
400Invalid payload
Content-Type: application/json
{
  "error": "string"
}
404Not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X PUT "http://108.165.128.56:3000/api/webhooks/webhooks" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"description\": null,
  \"httpMethod\": \"POST\",
  \"customHeaders\": null,
  \"deliveryStrategy\": \"http\",
  \"strategyConfig\": null,
  \"maxRetries\": 10,
  \"timeoutMs\": 15000,
  \"rateLimitPerMinute\": 0,
  \"autoDisableThreshold\": 100,
  \"integrationId\": null
}"
DELETE/webhooks/webhooks
Auth required

Delete webhook

Soft-deletes a webhook endpoint.

Parameters

NameInRequiredSchemaDescription
idqueryYesanyWebhook ID to delete

Responses

200Deleted
Content-Type: application/json
{
  "success": true
}
403Forbidden
Content-Type: application/json
{
  "error": "string"
}
404Not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/webhooks/webhooks?id=00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/webhooks/webhooks/{id}
Auth required

Get webhook

Returns webhook configuration, masked secret metadata, and delivery settings.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Webhook detail
Content-Type: application/json
{
  "id": "string",
  "name": "string",
  "description": null,
  "url": "string",
  "subscribedEvents": [
    "string"
  ],
  "httpMethod": "string",
  "isActive": true,
  "deliveryStrategy": "string",
  "maxRetries": 1,
  "consecutiveFailures": 1,
  "lastSuccessAt": null,
  "lastFailureAt": null,
  "createdAt": "string",
  "updatedAt": "string",
  "customHeaders": null,
  "strategyConfig": null,
  "timeoutMs": 1,
  "rateLimitPerMinute": 1,
  "autoDisableThreshold": 1,
  "integrationId": null,
  "maskedSecret": "string",
  "previousSecretSetAt": null
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
404Webhook not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/webhooks/webhooks/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"

Rich Methods Communications

Showing 9 of 9 endpoints
POST/richmethods_communications/callbacks/{providerKey}

Receive a provider status or call callback

Verifies the provider signature, resolves the tenant from the verifying channel, and applies a normalized status. Never sends anything.

Parameters

NameInRequiredSchemaDescription
providerKeypathYesany—

Responses

202Accepted.
Content-Type: application/json
{
  "received": true,
  "result": "string"
}
401Unauthorized.
Content-Type: application/json
{
  "error": "string"
}
403Forbidden.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/richmethods_communications/callbacks/:providerKey" \
  -H "Accept: application/json"
GET/richmethods_communications/consents
Auth required

List contact consent records

Lists consent state per channel and address in the authenticated scope.

Responses

200Success.
Content-Type: application/json
{}
401Unauthorized.
Content-Type: application/json
{
  "error": "string"
}
403Forbidden.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_communications/consents" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
PUT/richmethods_communications/consents
Auth required

Set contact consent

Sets unknown, consented, opted_out, or suppressed for a channel address.

Request body (application/json)

{
  "channel": "email",
  "address": "string",
  "status": "unknown",
  "contactId": null,
  "source": "admin"
}

Responses

200Success.
Content-Type: application/json
{}
401Unauthorized.
Content-Type: application/json
{
  "error": "string"
}
403Forbidden.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X PUT "http://108.165.128.56:3000/api/richmethods_communications/consents" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"channel\": \"email\",
  \"address\": \"string\",
  \"status\": \"unknown\",
  \"contactId\": null,
  \"source\": \"admin\"
}"
GET/richmethods_communications/policies
Auth required

Get the communications policy

Returns the policy for the authenticated tenant and organization, or null when none exists (fail closed).

Responses

200Success.
Content-Type: application/json
{}
401Unauthorized.
Content-Type: application/json
{
  "error": "string"
}
403Forbidden.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_communications/policies" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
PUT/richmethods_communications/policies
Auth required

Create or update the communications policy

Optimistic-locked by updatedAt; returns 409 on conflict.

Request body (application/json)

{
  "allowedChannels": [
    "email"
  ],
  "outboundAllowed": true,
  "inboundAllowed": true,
  "assistantsAllowed": true,
  "approvalMode": "required",
  "requireConsentChannels": [
    "email"
  ],
  "supervisorUserId": null,
  "quietHours": {
    "enabled": true,
    "start": "string",
    "end": "string",
    "timezone": "string"
  },
  "maxPerContactPerDay": 1,
  "blockedPurposes": [
    "follow_up"
  ]
}

Responses

200Success.
Content-Type: application/json
{}
401Unauthorized.
Content-Type: application/json
{
  "error": "string"
}
403Forbidden.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X PUT "http://108.165.128.56:3000/api/richmethods_communications/policies" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"allowedChannels\": [
    \"email\"
  ],
  \"outboundAllowed\": true,
  \"inboundAllowed\": true,
  \"assistantsAllowed\": true,
  \"approvalMode\": \"required\",
  \"requireConsentChannels\": [
    \"email\"
  ],
  \"supervisorUserId\": null,
  \"quietHours\": {
    \"enabled\": true,
    \"start\": \"string\",
    \"end\": \"string\",
    \"timezone\": \"string\"
  },
  \"maxPerContactPerDay\": 1,
  \"blockedPurposes\": [
    \"follow_up\"
  ]
}"
GET/richmethods_communications/providers
Auth required

List communication providers

Lists registered provider adapters with declared capabilities and tenant connection state.

Responses

200Success.
Content-Type: application/json
{}
401Unauthorized.
Content-Type: application/json
{
  "error": "string"
}
403Forbidden.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_communications/providers" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/richmethods_communications/requests
Auth required

List communication requests

Lists the provider-neutral request ledger with native approval state reconciled.

Responses

200Success.
Content-Type: application/json
{}
401Unauthorized.
Content-Type: application/json
{
  "error": "string"
}
403Forbidden.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_communications/requests" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/richmethods_communications/requests
Auth required

Propose a communication

Records a proposal. Nothing is sent until policy, consent, and approval permit it.

Request body (application/json)

{
  "channel": "email",
  "recipientAddress": "string",
  "body": "string",
  "purpose": "follow_up",
  "contactId": null,
  "dealId": null
}

Responses

200Success.
Content-Type: application/json
{}
401Unauthorized.
Content-Type: application/json
{
  "error": "string"
}
403Forbidden.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/richmethods_communications/requests" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"channel\": \"email\",
  \"recipientAddress\": \"string\",
  \"body\": \"string\",
  \"purpose\": \"follow_up\",
  \"contactId\": null,
  \"dealId\": null
}"
PUT/richmethods_communications/requests
Auth required

Act on a communication request

Submit for native approval, cancel, or escalate to the supervising human.

Request body (application/json)

{
  "id": "00000000-0000-4000-8000-000000000000",
  "action": "submit_for_approval"
}

Responses

200Success.
Content-Type: application/json
{}
401Unauthorized.
Content-Type: application/json
{
  "error": "string"
}
403Forbidden.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X PUT "http://108.165.128.56:3000/api/richmethods_communications/requests" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"action\": \"submit_for_approval\"
}"

Rich Methods Support

Showing 20 of 30 endpoints
GET/richmethods_support/cases

List support cases for the authenticated customer organization

Returns a bounded, organization-scoped list. Encrypted subjects are decrypted only for the authorized customer organization.

Responses

200The organization support cases.
Content-Type: application/json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "category": "ask_for_help",
      "impact": "general",
      "severity": "normal",
      "assigneeUserId": null,
      "status": "open",
      "subject": "string",
      "firstStaffResponseAt": null,
      "responseDueAt": null,
      "responseTimezone": null,
      "escalatedAt": null,
      "relatedProductKey": null,
      "relatedKnownIssuePostId": null,
      "relatedKnownIssue": null,
      "repeatReportCount": 1,
      "updatedAt": "string"
    }
  ]
}
401Authentication required.
Content-Type: application/json
{
  "error": "string"
}
403Forbidden.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_support/cases" \
  -H "Accept: application/json"
POST/richmethods_support/cases

Create a private support case

Creates a case and its initial encrypted message atomically. Impact determines severity using deterministic rules; retries with the same idempotency key do not create a second case.

Request body (application/json)

{
  "category": "ask_for_help",
  "impact": "general",
  "subject": "string",
  "message": "string",
  "idempotencyKey": "string"
}

Responses

201The created case reference.
Content-Type: application/json
{
  "item": {
    "id": "00000000-0000-4000-8000-000000000000",
    "status": "open",
    "severity": "normal",
    "duplicate": true
  }
}
400The request is invalid.
Content-Type: application/json
"string"
401Customer authentication is required.
Content-Type: application/json
"string"
403Case creation is not permitted.
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/richmethods_support/cases" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"category\": \"ask_for_help\",
  \"impact\": \"general\",
  \"subject\": \"string\",
  \"message\": \"string\",
  \"idempotencyKey\": \"string\"
}"
GET/richmethods_support/cases/{id}

Read a private support case

Returns the case and its encrypted-message history only when the authenticated customer belongs to the owning organization.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200The case detail, or null when it is not visible in this organization.
Content-Type: application/json
{
  "item": null
}
400The case ID is invalid.
Content-Type: application/json
"string"
401Customer authentication is required.
Content-Type: application/json
"string"
403Case access is not permitted.
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_support/cases/:id" \
  -H "Accept: application/json"
POST/richmethods_support/cases/{id}

Reply to a private support case

Appends an encrypted customer reply to a case in the authenticated organization. The UUID idempotency key prevents duplicate messages; resolved cases must first be reopened by staff.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Request body (application/json)

{
  "idempotencyKey": "00000000-0000-4000-8000-000000000000",
  "body": "string"
}

Responses

200An idempotent replay of the existing reply.
Content-Type: application/json
{
  "item": {
    "id": "00000000-0000-4000-8000-000000000000",
    "caseId": "00000000-0000-4000-8000-000000000000",
    "authorType": "customer",
    "body": "string",
    "createdAt": "string",
    "duplicate": true
  }
}
201The newly created reply.
Content-Type: application/json
{
  "item": {
    "id": "00000000-0000-4000-8000-000000000000",
    "caseId": "00000000-0000-4000-8000-000000000000",
    "authorType": "customer",
    "body": "string",
    "createdAt": "string",
    "duplicate": true
  }
}
400The case ID or request is invalid.
Content-Type: application/json
"string"
401Customer authentication is required.
Content-Type: application/json
"string"
403The caller cannot reply to support cases.
Content-Type: application/json
"string"
404The case is not available in this organization.
Content-Type: application/json
"string"
409The case is resolved or the idempotency key conflicts.
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/richmethods_support/cases/:id" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"idempotencyKey\": \"00000000-0000-4000-8000-000000000000\",
  \"body\": \"string\"
}"
GET/richmethods_support/community/posts/{id}/comments

Read member replies to a community post

Returns at most 200 comments after validating the post’s enabled segment and active membership for the authenticated customer in its organization.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200The ordered community comments.
Content-Type: application/json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "postId": "00000000-0000-4000-8000-000000000000",
      "parentId": null,
      "authorType": "customer",
      "body": "string",
      "createdAt": "string",
      "children": []
    }
  ]
}
400The post ID is invalid.
Content-Type: application/json
"string"
401Customer authentication is required.
Content-Type: application/json
"string"
403Active community membership is required.
Content-Type: application/json
"string"
404The post is unavailable in this scope.
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_support/community/posts/:id/comments" \
  -H "Accept: application/json"
POST/richmethods_support/community/posts/{id}/comments

Reply to a community post

Creates an encrypted, idempotent customer comment only for an active member of the post’s enabled segment when member posting is enabled. Private support cases remain separate.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Request body (application/json)

{
  "idempotencyKey": "00000000-0000-4000-8000-000000000000",
  "body": "string",
  "parentId": null
}

Responses

200An idempotent replay of the same comment.
Content-Type: application/json
{
  "item": {
    "id": "00000000-0000-4000-8000-000000000000",
    "postId": "00000000-0000-4000-8000-000000000000",
    "parentId": null,
    "authorType": "customer",
    "body": "string",
    "createdAt": "string",
    "children": [],
    "duplicate": true
  }
}
201The new comment.
Content-Type: application/json
{
  "item": {
    "id": "00000000-0000-4000-8000-000000000000",
    "postId": "00000000-0000-4000-8000-000000000000",
    "parentId": null,
    "authorType": "customer",
    "body": "string",
    "createdAt": "string",
    "children": [],
    "duplicate": true
  }
}
400The post ID or comment is invalid.
Content-Type: application/json
"string"
401Customer authentication is required.
Content-Type: application/json
"string"
403Membership or member-posting permission is required.
Content-Type: application/json
"string"
404The post is unavailable in this scope.
Content-Type: application/json
"string"
409The idempotency key is already used for different content.
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/richmethods_support/community/posts/:id/comments" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"idempotencyKey\": \"00000000-0000-4000-8000-000000000000\",
  \"body\": \"string\",
  \"parentId\": null
}"
GET/richmethods_support/community/segments

List available community segments

Lists enabled segments owned by the authenticated organization and segments explicitly configured for tenant-wide membership. Membership state is scoped to the authenticated customer user and organization.

Responses

200Available community segments.
Content-Type: application/json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "key": "string",
      "name": "string",
      "description": "string",
      "kind": "general",
      "audience": "organization",
      "memberPostsEnabled": true,
      "enabled": true,
      "updatedAt": "string",
      "isMember": true,
      "membershipUpdatedAt": null
    }
  ]
}
401Customer authentication is required.
Content-Type: application/json
"string"
403Community access is not permitted.
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_support/community/segments" \
  -H "Accept: application/json"
POST/richmethods_support/community/segments/{id}/membership

Opt in or out of a community segment

Changes only the authenticated customer user’s membership in an enabled segment available to their organization. Leaving a current membership requires its latest updatedAt version.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Request body (application/json)

{
  "action": "join"
}

Responses

200The current membership state.
Content-Type: application/json
{
  "item": {
    "segmentId": "00000000-0000-4000-8000-000000000000",
    "active": true,
    "updatedAt": null,
    "duplicate": true
  }
}
400The segment ID or request is invalid.
Content-Type: application/json
"string"
401Customer authentication is required.
Content-Type: application/json
"string"
403Membership changes are not permitted.
Content-Type: application/json
"string"
404The segment is unavailable in this scope.
Content-Type: application/json
"string"
409The membership version is stale.
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/richmethods_support/community/segments/:id/membership" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"action\": \"join\"
}"
GET/richmethods_support/community/segments/{id}/posts

Read a community feed

Returns up to 100 posts only after confirming active membership for the authenticated user and organization. Tenant-wide segments expose community posts only within that same tenant and segment.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200The membership-gated feed.
Content-Type: application/json
{
  "item": null
}
400The segment ID is invalid.
Content-Type: application/json
"string"
401Customer authentication is required.
Content-Type: application/json
"string"
403Active community membership is required.
Content-Type: application/json
"string"
404The segment is not available in this scope.
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_support/community/segments/:id/posts" \
  -H "Accept: application/json"
POST/richmethods_support/community/segments/{id}/posts

Create a community post

Creates an explicitly shared discussion post only for an enabled segment that permits member posts and has an active membership. Private support cases are stored separately and cannot be linked or copied through this API.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Request body (application/json)

{
  "idempotencyKey": "00000000-0000-4000-8000-000000000000",
  "title": "string",
  "body": "string"
}

Responses

200An idempotent replay of the same post.
Content-Type: application/json
{
  "item": {
    "id": "00000000-0000-4000-8000-000000000000",
    "segmentId": "00000000-0000-4000-8000-000000000000",
    "kind": "discussion",
    "title": "string",
    "body": "string",
    "authorType": "customer",
    "createdAt": "string",
    "duplicate": true
  }
}
201The new community post.
Content-Type: application/json
{
  "item": {
    "id": "00000000-0000-4000-8000-000000000000",
    "segmentId": "00000000-0000-4000-8000-000000000000",
    "kind": "discussion",
    "title": "string",
    "body": "string",
    "authorType": "customer",
    "createdAt": "string",
    "duplicate": true
  }
}
400The segment ID or post is invalid.
Content-Type: application/json
"string"
401Customer authentication is required.
Content-Type: application/json
"string"
403Posting requires active membership and segment permission.
Content-Type: application/json
"string"
404The segment is not available in this scope.
Content-Type: application/json
"string"
409The idempotency key is already used for different content.
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/richmethods_support/community/segments/:id/posts" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"idempotencyKey\": \"00000000-0000-4000-8000-000000000000\",
  \"title\": \"string\",
  \"body\": \"string\"
}"
GET/richmethods_support/feedback

List feedback submitted by the authenticated beta tester

Returns a bounded list of feedback reports in the customer’s authenticated organization.

Responses

200The customer’s feedback reports.
Content-Type: application/json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "caseId": "00000000-0000-4000-8000-000000000000",
      "category": "bug",
      "easeRating": 1,
      "featureKey": "business_setup",
      "applicationVersion": "string",
      "status": "open",
      "priority": "LOW",
      "subject": "string",
      "createdAt": "string",
      "updatedAt": "string"
    }
  ]
}
401Authentication required.
Content-Type: application/json
{
  "error": "string"
}
403Forbidden.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_support/feedback" \
  -H "Accept: application/json"
POST/richmethods_support/feedback

Submit beta feedback

Creates an idempotent feedback report. User, tenant, organization, and application version are derived by the server.

Request body (application/json)

{
  "category": "bug",
  "easeRating": 1,
  "featureKey": "business_setup",
  "idempotencyKey": "00000000-0000-4000-8000-000000000000"
}

Responses

201The created report reference.
Content-Type: application/json
{
  "item": {
    "id": "00000000-0000-4000-8000-000000000000",
    "reference": "string",
    "status": "open",
    "createdAt": "string",
    "duplicate": true
  }
}
400The request is invalid.
Content-Type: application/json
"string"
401Customer authentication is required.
Content-Type: application/json
"string"
403Feedback submission is not permitted.
Content-Type: application/json
"string"
409The idempotency key is already used for another support operation.
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/richmethods_support/feedback" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"category\": \"bug\",
  \"easeRating\": 1,
  \"featureKey\": \"business_setup\",
  \"idempotencyKey\": \"00000000-0000-4000-8000-000000000000\"
}"
GET/richmethods_support/feedback/{id}

Read one feedback report and its private conversation

Returns the authenticated tester’s feedback record and support replies within the current organization.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200The feedback report and messages.
Content-Type: application/json
{
  "item": {
    "id": "00000000-0000-4000-8000-000000000000",
    "reference": "string",
    "category": "bug",
    "easeRating": 1,
    "featureKey": "string",
    "applicationVersion": "string",
    "status": "open",
    "priority": "LOW",
    "subject": "string",
    "createdAt": "string",
    "updatedAt": "string",
    "screenshotAttachmentIds": [
      "00000000-0000-4000-8000-000000000000"
    ],
    "messages": [
      {
        "id": "00000000-0000-4000-8000-000000000000",
        "authorType": "customer",
        "body": "string",
        "createdAt": "string"
      }
    ]
  }
}
400The feedback ID is invalid.
Content-Type: application/json
"string"
401Authentication required.
Content-Type: application/json
{
  "error": "string"
}
403Forbidden.
Content-Type: application/json
{
  "error": "string"
}
404The feedback report is unavailable.
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_support/feedback/:id" \
  -H "Accept: application/json"
POST/richmethods_support/feedback/{id}/attachments

Attach a reviewed private screenshot to a beta feedback report

Accepts one metadata-stripped raster image for a report owned by the authenticated customer. The file is stored only in the private attachments partition.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

201The screenshot was attached.
Content-Type: application/json
{
  "item": {
    "attachmentId": "00000000-0000-4000-8000-000000000000",
    "duplicate": true
  }
}
400The upload form is invalid.
Content-Type: application/json
"string"
401Authentication required.
Content-Type: application/json
{
  "error": "string"
}
403Forbidden.
Content-Type: application/json
{
  "error": "string"
}
409The report changed or already has a screenshot.
Content-Type: application/json
"string"
413The image exceeds the allowed upload size.
Content-Type: application/json
"string"
415The file is not a supported raster image.
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/richmethods_support/feedback/:id/attachments" \
  -H "Accept: application/json"
GET/richmethods_support/feedback/{id}/attachments/{attachmentId}

Read an authorized beta feedback screenshot

Returns one private image only when it is linked to the authenticated tester’s own feedback report.

Parameters

NameInRequiredSchemaDescription
idpathYesany—
attachmentIdpathYesany—

Responses

200The private screenshot.
Content-Type: application/json
"string"
401Authentication required.
Content-Type: application/json
{
  "error": "string"
}
403Forbidden.
Content-Type: application/json
{
  "error": "string"
}
404The screenshot is unavailable.
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_support/feedback/:id/attachments/:attachmentId" \
  -H "Accept: application/json"
POST/richmethods_support/feedback/{id}/reply

Reply to one of the authenticated tester’s feedback reports

Adds an idempotent private message to the feedback conversation; it does not send external notifications.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Request body (application/json)

{
  "idempotencyKey": "00000000-0000-4000-8000-000000000000",
  "body": "string"
}

Responses

201The reply reference.
Content-Type: application/json
{
  "item": {
    "id": "00000000-0000-4000-8000-000000000000",
    "createdAt": "string",
    "duplicate": true
  }
}
400The request is invalid.
Content-Type: application/json
"string"
401Customer authentication is required.
Content-Type: application/json
"string"
403Feedback replies are not permitted.
Content-Type: application/json
"string"
404The feedback report is unavailable.
Content-Type: application/json
"string"
409The report changed or the idempotency key conflicts.
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/richmethods_support/feedback/:id/reply" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"idempotencyKey\": \"00000000-0000-4000-8000-000000000000\",
  \"body\": \"string\"
}"
GET/richmethods_support/staff/beta-health
Auth required

Read scoped support and community metrics

Returns exact aggregate counts for cases and community segments owned by the active organization. Cross-organization customer content and message bodies are never returned. Access requires the dedicated support Beta Health grant.

Responses

200Measured counts from support and community source records, including true zero values.
Content-Type: application/json
{
  "availability": "measured",
  "cases": {
    "total": 1,
    "active": 1,
    "critical": 1,
    "problemReports": 1,
    "featureRequests": 1,
    "feedback": 1
  },
  "community": {
    "segments": 1,
    "activeMemberships": 1,
    "posts": 1
  }
}
401Staff authentication is required.
Content-Type: application/json
"string"
403The caller cannot view scoped Beta Health metrics.
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_support/staff/beta-health" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/richmethods_support/staff/calendar
Auth required

Read the authenticated organization support calendar

Returns the configured IANA timezone or null when response deadlines are not configured.

Responses

200The organization support calendar.
Content-Type: application/json
{
  "item": {
    "timezone": null,
    "updatedAt": null
  }
}
401Staff authentication is required.
Content-Type: application/json
"string"
403The caller cannot manage the support calendar.
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_support/staff/calendar" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
PUT/richmethods_support/staff/calendar
Auth required

Configure the organization support calendar timezone

Sets weekday support hours to 09:00-17:00 in the supplied IANA timezone. A null version is required for initial setup; subsequent updates require the current updatedAt value.

Request body (application/json)

{
  "timezone": "string",
  "updatedAt": null
}

Responses

200The configured support calendar.
Content-Type: application/json
{
  "item": {
    "timezone": null,
    "updatedAt": null,
    "duplicate": true
  }
}
400The timezone or request is invalid.
Content-Type: application/json
"string"
401Staff authentication is required.
Content-Type: application/json
"string"
403The caller cannot manage the support calendar.
Content-Type: application/json
"string"
409The support calendar changed before this update was saved.
Content-Type: application/json
"string"

Example

curl -X PUT "http://108.165.128.56:3000/api/richmethods_support/staff/calendar" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"timezone\": \"string\",
  \"updatedAt\": null
}"
GET/richmethods_support/staff/cases
Auth required

List support cases for the authenticated staff organization

Returns up to 50 cases per priority, ordered urgent, high, normal, then low; overdue escalations lead within each priority. Matching uses the same related product, category, and impact, and is a visibility signal rather than a confirmed duplicate. The optional status query selects active (open and in-progress, the default) or resolved cases. The response includes support triage permission signals and response-target state; the list exposes no message bodies.

Responses

200The prioritized support queue.
Content-Type: application/json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "category": "ask_for_help",
      "impact": "general",
      "severity": "normal",
      "assigneeUserId": null,
      "status": "open",
      "subject": "string",
      "firstStaffResponseAt": null,
      "responseDueAt": null,
      "responseTimezone": null,
      "escalatedAt": null,
      "relatedProductKey": null,
      "relatedKnownIssuePostId": null,
      "relatedKnownIssue": null,
      "repeatReportCount": 1,
      "updatedAt": "string"
    }
  ],
  "canManage": true,
  "canLinkKnownIssue": true,
  "canManageCalendar": true,
  "viewerUserId": "00000000-0000-4000-8000-000000000000"
}
400The requested status filter is invalid.
Content-Type: application/json
"string"
401Staff authentication is required.
Content-Type: application/json
"string"
403The caller cannot view the support queue.
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_support/staff/cases" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"

Scheduler

Showing 8 of 8 endpoints
GET/scheduler/jobs
Auth required

List scheduledjobs

Returns a paginated collection of scheduledjobs scoped to the authenticated organization.

Parameters

NameInRequiredSchemaDescription
pagequeryNoany—
pageSizequeryNoany—
idqueryNoany—
searchqueryNoany—
scopeTypequeryNoany—
isEnabledqueryYesany—
sourceTypequeryNoany—
sourceModulequeryNoany—
sortqueryNoany—
orderqueryNoany—
idsqueryNoanyComma-separated list of record UUIDs to filter by (max 200).

Responses

200Paginated scheduledjobs
Content-Type: application/json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "name": "string",
      "description": null,
      "scopeType": "system",
      "organizationId": null,
      "tenantId": null,
      "scheduleType": "cron",
      "scheduleValue": "string",
      "timezone": "string",
      "targetType": "queue",
      "targetQueue": null,
      "targetCommand": null,
      "targetPayload": null,
      "requireFeature": null,
      "isEnabled": true,
      "lastRunAt": null,
      "nextRunAt": null,
      "sourceType": "user",
      "sourceModule": null,
      "createdAt": "string",
      "updatedAt": "string"
    }
  ],
  "total": 1,
  "totalPages": 1
}

Example

curl -X GET "http://108.165.128.56:3000/api/scheduler/jobs?page=1&pageSize=20" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/scheduler/jobs
Auth required

Create scheduledjob

Creates a new scheduled job with cron or interval-based scheduling.

Request body (application/json)

{
  "name": "string",
  "description": null,
  "scopeType": "system",
  "organizationId": null,
  "tenantId": null,
  "scheduleType": "cron",
  "scheduleValue": "string",
  "timezone": "UTC",
  "targetType": "queue",
  "targetQueue": null,
  "targetCommand": null,
  "targetPayload": null,
  "requireFeature": null,
  "isEnabled": true
}

Responses

201ScheduledJob created
Content-Type: application/json
{
  "id": null
}

Example

curl -X POST "http://108.165.128.56:3000/api/scheduler/jobs" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"name\": \"string\",
  \"description\": null,
  \"scopeType\": \"system\",
  \"organizationId\": null,
  \"tenantId\": null,
  \"scheduleType\": \"cron\",
  \"scheduleValue\": \"string\",
  \"timezone\": \"UTC\",
  \"targetType\": \"queue\",
  \"targetQueue\": null,
  \"targetCommand\": null,
  \"targetPayload\": null,
  \"requireFeature\": null,
  \"isEnabled\": true
}"
PUT/scheduler/jobs
Auth required

Update scheduledjob

Updates an existing scheduled job by ID.

Request body (application/json)

{
  "id": "string",
  "description": null,
  "targetQueue": null,
  "targetCommand": null,
  "targetPayload": null,
  "requireFeature": null
}

Responses

200ScheduledJob updated
Content-Type: application/json
{
  "ok": true
}

Example

curl -X PUT "http://108.165.128.56:3000/api/scheduler/jobs" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"string\",
  \"description\": null,
  \"targetQueue\": null,
  \"targetCommand\": null,
  \"targetPayload\": null,
  \"requireFeature\": null
}"
DELETE/scheduler/jobs
Auth required

Delete scheduledjob

Deletes a scheduled job by ID.

Request body (application/json)

{
  "id": "string"
}

Responses

200ScheduledJob deleted
Content-Type: application/json
{
  "ok": true
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/scheduler/jobs" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"string\"
}"
GET/scheduler/jobs/{id}/executions

Get execution history for a schedule

Fetch recent executions from BullMQ for a scheduled job. Requires QUEUE_STRATEGY=async.

Parameters

NameInRequiredSchemaDescription
idpathYesany—
pageSizequeryNoany—

Responses

200Execution history
Content-Type: application/json
{
  "items": [
    {
      "id": "string",
      "scheduleId": "00000000-0000-4000-8000-000000000000",
      "startedAt": "string",
      "finishedAt": null,
      "status": "running",
      "triggerType": "scheduled",
      "triggeredByUserId": null,
      "errorMessage": null,
      "errorStack": null,
      "durationMs": null,
      "queueJobId": "string",
      "queueName": "string",
      "attemptsMade": 1,
      "result": null
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1
}
400Local strategy not supported
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
403Access denied
Content-Type: application/json
{
  "error": "string"
}
404Schedule not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/scheduler/jobs/:id/executions?pageSize=20" \
  -H "Accept: application/json"
GET/scheduler/queue-jobs/{jobId}

Get BullMQ job details and logs

Fetch detailed information and logs for a queue job. Requires QUEUE_STRATEGY=async.

Parameters

NameInRequiredSchemaDescription
jobIdpathYesany—
queuequeryYesany—

Responses

200Job details and logs
Content-Type: application/json
{
  "id": "string",
  "name": "string",
  "state": "waiting",
  "progress": null,
  "returnvalue": null,
  "failedReason": null,
  "stacktrace": null,
  "attemptsMade": 1,
  "processedOn": null,
  "finishedOn": null,
  "logs": [
    "string"
  ]
}
400Invalid request or local strategy not supported
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
403Access denied
Content-Type: application/json
{
  "error": "string"
}
404Job not found
Content-Type: application/json
{
  "error": "string"
}
500Internal server error
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/scheduler/queue-jobs/:jobId?queue=string" \
  -H "Accept: application/json"
GET/scheduler/targets

List available queues and commands

Returns available queue names and scheduler-safe command IDs for schedule target selection.

Responses

200Available targets
Content-Type: application/json
{
  "queues": [
    {
      "value": "string",
      "label": "string"
    }
  ],
  "commands": [
    {
      "value": "string",
      "label": "string"
    }
  ]
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/scheduler/targets" \
  -H "Accept: application/json"
POST/scheduler/trigger

Manually trigger a schedule

Executes a scheduled job immediately, bypassing the scheduled time. Only works with async queue strategy. The attempt is audited against the calling user whether it succeeds, is refused, or fails, except when a before command interceptor blocks it before the command runs.

Request body (application/json)

{
  "id": "string"
}

Responses

200Schedule triggered successfully
Content-Type: application/json
{
  "ok": true,
  "jobId": "string",
  "message": "string"
}
400Invalid request or local strategy not supported
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
403Access denied
Content-Type: application/json
{
  "error": "string"
}
404Schedule not found
Content-Type: application/json
{
  "error": "string"
}
409Trigger deliberately blocked by a before command interceptor. The interceptor chooses the status (any 4xx/5xx) and may replace the body.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/scheduler/trigger" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"string\"
}"

Auth

Showing 1 of 1 endpoints
GET/auth/users/consents
Auth required

List user consents

Returns all consent records for a given user, with integrity verification status.

Parameters

NameInRequiredSchemaDescription
userIdqueryYesany—

Responses

200Consent list returned
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/auth/users/consents?userId=00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"

CommunicationChannels

Showing 20 of 21 endpoints
DELETE/communication_channels/admin/channels/{id}
Auth required

Admin delete (soft-delete) a tenant-wide communication channel

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

204Channel deleted

No response body.

400Invalid channel id
Content-Type: application/json
"string"
401Unauthorized
Content-Type: application/json
"string"
404Channel not found or not a tenant-wide channel
Content-Type: application/json
"string"

Example

curl -X DELETE "http://108.165.128.56:3000/api/communication_channels/admin/channels/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/communication_channels/channels
Auth required

List communication channels for the current tenant

Responses

200Channel list (paginated)
Content-Type: application/json
"string"
400Invalid query parameters
Content-Type: application/json
"string"
401Unauthorized
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/communication_channels/channels" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/communication_channels/channels/{id}
Auth required

Get a single communication channel by id

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Channel detail
Content-Type: application/json
"string"
400Invalid channel id
Content-Type: application/json
"string"
401Unauthorized
Content-Type: application/json
"string"
404Channel not found
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/communication_channels/channels/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/communication_channels/channels/{id}/health
Auth required

Snapshot of channel delivery health (last 24h)

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Health snapshot
Content-Type: application/json
"string"
400Invalid channel id
Content-Type: application/json
"string"
401Unauthorized
Content-Type: application/json
"string"
404Channel not found
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/communication_channels/channels/:id/health" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/communication_channels/channels/{id}/import-history
Auth required

Queue a backlog import for a channel (Spec B § Phase B6)

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Request body (application/json)

{
  "sinceDays": 30,
  "maxMessages": 1000
}

Responses

202Import job queued; returns { progressJobId }
Content-Type: application/json
"string"
400Invalid channel id or unsupported provider
Content-Type: application/json
"string"
401Unauthorized
Content-Type: application/json
"string"
404Channel not found / not accessible
Content-Type: application/json
"string"
409Channel is not connected (requires reauth / error)
Content-Type: application/json
"string"
429Another import is already running for this channel
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/communication_channels/channels/:id/import-history" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"sinceDays\": 30,
  \"maxMessages\": 1000
}"
POST/communication_channels/channels/{id}/poll-now
Auth required

Manually trigger a poll cycle for a channel (demo / operator override)

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

202Poll job enqueued
Content-Type: application/json
"string"
400Invalid channel id
Content-Type: application/json
"string"
401Unauthorized
Content-Type: application/json
"string"
404Channel not found
Content-Type: application/json
"string"
409Channel disabled, not connected, or push-driven (never polled)
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/communication_channels/channels/:id/poll-now" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/communication_channels/channels/{id}/push/register
Auth required

Force-register push delivery for a channel (Spec C § Phase C5)

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

202Push registration attempted; check result.pushStatus
Content-Type: application/json
"string"
400Invalid id or unsupported provider
Content-Type: application/json
"string"
401Unauthorized
Content-Type: application/json
"string"
403Missing push.manage feature
Content-Type: application/json
"string"
404Channel not found
Content-Type: application/json
"string"
409Provider does not support push (IMAP)
Content-Type: application/json
"string"
502Provider returned an error during registration
Content-Type: application/json
"string"
503Webhook base URL or Pub/Sub topic not configured
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/communication_channels/channels/:id/push/register" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/communication_channels/channels/{id}/set-primary
Auth required

Mark a per-user channel as primary

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Channel set as primary (or already primary)
Content-Type: application/json
"string"
400Invalid channel id
Content-Type: application/json
"string"
401Unauthorized
Content-Type: application/json
"string"
404Channel not found or not owned by current user
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/communication_channels/channels/:id/set-primary" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/communication_channels/channels/{id}/test-send
Auth required

Diagnostic — send a test message through the channel without persisting

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Test send result
Content-Type: application/json
"string"
400Invalid channel id
Content-Type: application/json
"string"
401Unauthorized
Content-Type: application/json
"string"
403Not allowed to manage this channel
Content-Type: application/json
"string"
404Channel or adapter not found
Content-Type: application/json
"string"
409Channel not connected
Content-Type: application/json
"string"
422Invalid request body
Content-Type: application/json
"string"
502Provider error
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/communication_channels/channels/:id/test-send" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/communication_channels/channels/connect/credentials
Auth required

Connect a credential-based per-user channel (IMAP/SMTP)

Responses

201Channel connected
Content-Type: application/json
"string"
401Unauthorized
Content-Type: application/json
"string"
403Provider is tenant-scoped — use the tenant connect route
Content-Type: application/json
"string"
404Unknown provider
Content-Type: application/json
"string"
409Mailbox already connected via another provider
Content-Type: application/json
"string"
422Invalid body or credential validation failed
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/communication_channels/channels/connect/credentials" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/communication_channels/channels/connect/tenant-credentials
Auth required

Connect a tenant-wide credential-based channel (push: FCM/APNs/Expo)

Responses

201Channel connected
Content-Type: application/json
"string"
400Provider is not tenant-scoped
Content-Type: application/json
"string"
401Unauthorized
Content-Type: application/json
"string"
404Unknown provider
Content-Type: application/json
"string"
422Invalid body or credential validation failed
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/communication_channels/channels/connect/tenant-credentials" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/communication_channels/me/channels
Auth required

List the current user's connected channels

Responses

200List of user-owned channels
Content-Type: application/json
"string"
401Unauthorized
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/communication_channels/me/channels" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/communication_channels/messages/{messageId}/reactions
Auth required

Add a reaction to a channel-linked message

Parameters

NameInRequiredSchemaDescription
messageIdpathYesany—

Responses

201Reaction added
Content-Type: application/json
"string"
400Invalid messageId
Content-Type: application/json
"string"
401Unauthorized
Content-Type: application/json
"string"
403Channel is owned by another user
Content-Type: application/json
"string"
409Message not channel-linked or duplicate reaction
Content-Type: application/json
"string"
422Invalid request body
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/communication_channels/messages/:messageId/reactions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
DELETE/communication_channels/messages/{messageId}/reactions/{reactionId}
Auth required

Remove a reaction from a channel-linked message

Parameters

NameInRequiredSchemaDescription
messageIdpathYesany—
reactionIdpathYesany—

Responses

204Reaction removed

No response body.

400Invalid params
Content-Type: application/json
"string"
401Unauthorized
Content-Type: application/json
"string"
403Channel is owned by another user
Content-Type: application/json
"string"
404Reaction not found or not owned by current user
Content-Type: application/json
"string"
409Message not channel-linked
Content-Type: application/json
"string"

Example

curl -X DELETE "http://108.165.128.56:3000/api/communication_channels/messages/:messageId/reactions/:reactionId" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/communication_channels/oauth/{provider}/callback
Auth required

OAuth callback — exchange code, persist credentials, create per-user channel

Parameters

NameInRequiredSchemaDescription
providerpathYesany—

Responses

200Success response
Content-Type: application/json
"string"
302Redirect back to returnUrl with flash query params
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/communication_channels/oauth/:provider/callback" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/communication_channels/oauth/{provider}/initiate
Auth required

Start a per-user channel OAuth flow

Parameters

NameInRequiredSchemaDescription
providerpathYesany—

Responses

200Authorize URL + state cookie set
Content-Type: application/json
"string"
400Invalid provider or unsupported (no OAuth)
Content-Type: application/json
"string"
401Unauthorized
Content-Type: application/json
"string"
422Invalid request body
Content-Type: application/json
"string"
502Adapter failed to build authorize URL
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/communication_channels/oauth/:provider/initiate" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/communication_channels/send-as-user
Auth required

Send a message through the current user's own channel

Responses

202Message persisted; outbound delivery enqueued
Content-Type: application/json
"string"
401Unauthorized
Content-Type: application/json
"string"
403Cannot send through a channel you don't own
Content-Type: application/json
"string"
404Channel not found
Content-Type: application/json
"string"
409Channel in a non-deliverable transitional status
Content-Type: application/json
"string"
422Invalid body, or channel requires_reauth / disconnected
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/communication_channels/send-as-user" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/communication_channels/test-seed
Auth required

Test-only: seed a connected channel, ingest a real inbound message, or emit a seeded inbound link (env-gated)

Responses

201Channel seeded / inbound message emitted
Content-Type: application/json
"string"
401Unauthorized
Content-Type: application/json
"string"
404Test channel seeding disabled (production default), or the requested channel does not belong to the caller
Content-Type: application/json
"string"
422Invalid request body
Content-Type: application/json
"string"
500Seed failed
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/communication_channels/test-seed" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
PUT/communication_channels/threads/{threadId}/assign
Auth required

Reassign a channel-linked conversation to a different owner

Parameters

NameInRequiredSchemaDescription
threadIdpathYesany—

Responses

200Conversation reassigned (or unchanged)
Content-Type: application/json
"string"
400Invalid threadId
Content-Type: application/json
"string"
401Unauthorized
Content-Type: application/json
"string"
404Conversation not channel-linked
Content-Type: application/json
"string"
422Invalid request body
Content-Type: application/json
"string"

Example

curl -X PUT "http://108.165.128.56:3000/api/communication_channels/threads/:threadId/assign" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/communication_channels/webhook/{provider}

Process an inbound channel webhook (Slack, WhatsApp, Email, ...)

Parameters

NameInRequiredSchemaDescription
providerpathYesany—

Responses

202Webhook accepted for async processing
Content-Type: application/json
"string"
401Signature verification failed against every candidate channel
Content-Type: application/json
"string"
404Unknown provider
Content-Type: application/json
"string"
413Webhook payload too large
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/communication_channels/webhook/:provider" \
  -H "Accept: application/json"

Configs

Showing 8 of 8 endpoints
GET/configs/cache
Auth required

Get cache statistics

Returns detailed cache statistics including total entries and breakdown by cache segments. Requires cache service to be available.

Responses

200Cache statistics
Content-Type: application/json
{
  "generatedAt": "string",
  "totalKeys": 1,
  "segments": [
    {
      "segment": "string",
      "resource": null,
      "method": null,
      "path": null,
      "keyCount": 1,
      "keys": [
        "string"
      ]
    }
  ]
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
500Failed to resolve cache stats
Content-Type: application/json
{
  "error": "string"
}
503Cache service unavailable
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/configs/cache" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/configs/cache
Auth required

Purge cache

Purges cache entries. Supports two actions: purgeAll (clears entire cache) or purgeSegment (clears specific segment). Returns updated cache statistics after purge.

Request body (application/json)

{
  "action": "purgeAll"
}

Responses

200Cache segment cleared successfully
Content-Type: application/json
{
  "action": "purgeSegment",
  "segment": "string",
  "deleted": 1,
  "stats": {
    "generatedAt": "string",
    "totalKeys": 1,
    "segments": [
      {
        "segment": "string",
        "resource": null,
        "method": null,
        "path": null,
        "keyCount": 1,
        "keys": [
          "string"
        ]
      }
    ]
  }
}
400Invalid request - missing segment identifier for purgeSegment action
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
500Failed to purge cache
Content-Type: application/json
{
  "error": "string"
}
503Cache service unavailable
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/configs/cache" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"action\": \"purgeAll\"
}"
GET/configs/module-telemetry
Auth required

Get module resource usage telemetry

Returns in-process module resource attribution for API routes, event subscribers, and queue workers.

Responses

200Module resource usage report
Content-Type: application/json
{
  "generatedAt": "string",
  "startedAt": "string",
  "enabled": true,
  "bucketIntervalMs": 1,
  "totals": {
    "modules": 1,
    "operations": 1,
    "calls": 1,
    "errors": 1,
    "totalDurationMs": 1,
    "totalCpuMs": 1,
    "positiveHeapDeltaBytes": 1,
    "positiveRssDeltaBytes": 1
  },
  "thresholds": {
    "p95DurationMs": 1,
    "cpuMs": 1,
    "positiveHeapDeltaBytes": 1,
    "positiveRssDeltaBytes": 1,
    "errors": 1
  },
  "modules": [
    {
      "moduleId": "string",
      "calls": 1,
      "errors": 1,
      "totalDurationMs": 1,
      "p95DurationMs": 1,
      "totalCpuMs": 1,
      "positiveHeapDeltaBytes": 1,
      "positiveRssDeltaBytes": 1,
      "surfaces": [
        {
          "surface": "api",
          "calls": 1,
          "errors": 1,
          "totalDurationMs": 1,
          "p95DurationMs": 1,
          "totalCpuMs": 1,
          "positiveHeapDeltaBytes": 1,
          "positiveRssDeltaBytes": 1
        }
      ],
      "topOperations": [
        {
          "moduleId": "string",
          "surface": "api",
          "operation": "string",
          "resourceId": null,
          "calls": 1,
          "errors": 1,
          "totalDurationMs": 1,
          "maxDurationMs": 1,
          "p95DurationMs": 1,
          "totalCpuUserMs": 1,
          "totalCpuSystemMs": 1,
          "maxCpuMs": 1,
          "totalHeapDeltaBytes": 1,
          "positiveHeapDeltaBytes": 1,
          "maxHeapDeltaBytes": 1,
          "totalRssDeltaBytes": 1,
          "positiveRssDeltaBytes": 1,
          "maxRssDeltaBytes": 1,
          "firstSeenAt": "string",
          "lastSeenAt": "string"
        }
      ],
      "candidateReasons": [
        "string"
      ]
    }
  ],
  "candidates": [
    {
      "moduleId": "string",
      "calls": 1,
      "errors": 1,
      "totalDurationMs": 1,
      "p95DurationMs": 1,
      "totalCpuMs": 1,
      "positiveHeapDeltaBytes": 1,
      "positiveRssDeltaBytes": 1,
      "surfaces": [
        {
          "surface": "api",
          "calls": 1,
          "errors": 1,
          "totalDurationMs": 1,
          "p95DurationMs": 1,
          "totalCpuMs": 1,
          "positiveHeapDeltaBytes": 1,
          "positiveRssDeltaBytes": 1
        }
      ],
      "topOperations": [
        {
          "moduleId": "string",
          "surface": "api",
          "operation": "string",
          "resourceId": null,
          "calls": 1,
          "errors": 1,
          "totalDurationMs": 1,
          "maxDurationMs": 1,
          "p95DurationMs": 1,
          "totalCpuUserMs": 1,
          "totalCpuSystemMs": 1,
          "maxCpuMs": 1,
          "totalHeapDeltaBytes": 1,
          "positiveHeapDeltaBytes": 1,
          "maxHeapDeltaBytes": 1,
          "totalRssDeltaBytes": 1,
          "positiveRssDeltaBytes": 1,
          "maxRssDeltaBytes": 1,
          "firstSeenAt": "string",
          "lastSeenAt": "string"
        }
      ],
      "candidateReasons": [
        "string"
      ]
    }
  ],
  "buckets": [
    {
      "bucketStart": "string",
      "bucketEnd": "string",
      "bucketIntervalMs": 1,
      "stage": "startup",
      "partial": true,
      "totals": {
        "modules": 1,
        "calls": 1,
        "errors": 1,
        "totalDurationMs": 1,
        "totalCpuMs": 1,
        "positiveHeapDeltaBytes": 1,
        "positiveRssDeltaBytes": 1
      },
      "modules": [
        {
          "moduleId": "string",
          "calls": 1,
          "errors": 1,
          "totalDurationMs": 1,
          "p95DurationMs": 1,
          "totalCpuMs": 1,
          "positiveHeapDeltaBytes": 1,
          "positiveRssDeltaBytes": 1,
          "surfaces": [
            {
              "surface": "api",
              "calls": 1,
              "errors": 1,
              "totalDurationMs": 1,
              "p95DurationMs": 1,
              "totalCpuMs": 1,
              "positiveHeapDeltaBytes": 1,
              "positiveRssDeltaBytes": 1
            }
          ],
          "topOperations": [
            {
              "moduleId": "string",
              "surface": "api",
              "operation": "string",
              "resourceId": null,
              "calls": 1,
              "errors": 1,
              "totalDurationMs": 1,
              "maxDurationMs": 1,
              "p95DurationMs": 1,
              "totalCpuUserMs": 1,
              "totalCpuSystemMs": 1,
              "maxCpuMs": 1,
              "totalHeapDeltaBytes": 1,
              "positiveHeapDeltaBytes": 1,
              "maxHeapDeltaBytes": 1,
              "totalRssDeltaBytes": 1,
              "positiveRssDeltaBytes": 1,
              "maxRssDeltaBytes": 1,
              "firstSeenAt": "string",
              "lastSeenAt": "string"
            }
          ],
          "candidateReasons": [
            "string"
          ]
        }
      ]
    }
  ]
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/configs/module-telemetry" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
DELETE/configs/module-telemetry
Auth required

Clear module telemetry data

Development-only endpoint that clears in-memory module telemetry and local process telemetry files.

Responses

200Module telemetry cleared
Content-Type: application/json
{
  "cleared": true
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
403Forbidden outside development mode
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/configs/module-telemetry" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/configs/system-status
Auth required

Get system health status

Returns comprehensive system health information including environment details, version, resource usage, and service connectivity status.

Responses

200System status snapshot
Content-Type: application/json
{
  "generatedAt": "string",
  "runtimeMode": "development",
  "categories": [
    {
      "key": "profiling",
      "labelKey": "string",
      "descriptionKey": null,
      "items": [
        {
          "key": "string",
          "category": "profiling",
          "kind": "boolean",
          "labelKey": "string",
          "descriptionKey": "string",
          "docUrl": null,
          "defaultValue": null,
          "state": "enabled",
          "value": null,
          "normalizedValue": null
        }
      ]
    }
  ]
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
500Failed to load system status
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/configs/system-status" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/configs/system-status
Auth required

Clear system cache

Purges the entire cache for the current tenant. Useful for troubleshooting or forcing fresh data loading.

Responses

200Cache cleared successfully
Content-Type: application/json
{
  "cleared": true
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
500Failed to purge cache
Content-Type: application/json
{
  "error": "string"
}
503Cache service unavailable
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/configs/system-status" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/configs/upgrade-actions
Auth required

List pending upgrade actions

Returns a list of pending upgrade actions for the current version. These are one-time setup tasks that need to be executed after upgrading to a new version. Requires organization and tenant context.

Responses

200List of pending upgrade actions
Content-Type: application/json
{
  "version": "string",
  "actions": [
    {
      "id": "string",
      "version": "string",
      "message": "string",
      "ctaLabel": "string",
      "successMessage": "string",
      "loadingLabel": "string"
    }
  ]
}
400Missing organization or tenant context
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
500Failed to load upgrade actions
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/configs/upgrade-actions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/configs/upgrade-actions
Auth required

Execute upgrade action

Executes a specific upgrade action by ID. Typically used for one-time setup tasks like seeding example data after version upgrade. Returns execution status and localized success message.

Request body (application/json)

{
  "actionId": "string"
}

Responses

200Upgrade action executed successfully
Content-Type: application/json
{
  "status": "string",
  "message": "string",
  "version": "string"
}
400Invalid request body or missing context
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
403Upgrade actions are disabled
Content-Type: application/json
{
  "error": "string"
}
500Failed to execute upgrade action
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/configs/upgrade-actions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"actionId\": \"string\"
}"

Customer Accounts Admin

Showing 17 of 17 endpoints
GET/customer_accounts/admin/demo-accounts
Auth required

List seeded demo portal accounts (admin)

Returns the example-data portal accounts that exist in the caller’s organization and can still be logged into with the credentials the seeding hook created them with. Accounts that were deactivated, left unverified, soft-deleted, or had their password changed are omitted, as is every account when example data was not seeded.

Responses

200Seeded demo accounts present in the current organization
Content-Type: application/json
{
  "ok": true,
  "items": [
    {
      "email": "user@example.com",
      "password": "string",
      "roles": [
        {
          "id": "00000000-0000-4000-8000-000000000000",
          "name": "string",
          "slug": "string"
        }
      ]
    }
  ]
}
401Not authenticated
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
403Insufficient permissions
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/customer_accounts/admin/demo-accounts" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/customer_accounts/admin/roles

List customer roles (admin)

Returns all customer roles for the tenant.

Responses

200Role list
Content-Type: application/json
{
  "ok": true,
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "name": "string",
      "slug": "string",
      "description": null,
      "isDefault": true,
      "isSystem": true,
      "customerAssignable": true,
      "createdAt": "string",
      "updatedAt": null
    }
  ],
  "total": 1,
  "totalPages": 1,
  "page": 1
}
401Not authenticated
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
403Insufficient permissions
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/customer_accounts/admin/roles" \
  -H "Accept: application/json"
POST/customer_accounts/admin/roles

Create customer role (admin)

Creates a new customer role with an empty ACL.

Request body (application/json)

{
  "name": "string",
  "slug": "string"
}

Responses

201Role created
Content-Type: application/json
{
  "ok": true,
  "role": {
    "id": "00000000-0000-4000-8000-000000000000",
    "name": "string",
    "slug": "string",
    "description": null,
    "isDefault": true,
    "isSystem": true,
    "customerAssignable": true,
    "createdAt": "string"
  }
}
400Validation failed
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
401Not authenticated
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
403Insufficient permissions
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
409Slug already exists
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/customer_accounts/admin/roles" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"name\": \"string\",
  \"slug\": \"string\"
}"
GET/customer_accounts/admin/roles/{id}

Get customer role detail (admin)

Returns full customer role details including ACL features.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Role detail with ACL
Content-Type: application/json
{
  "ok": true,
  "role": {
    "id": "00000000-0000-4000-8000-000000000000",
    "name": "string",
    "slug": "string",
    "description": null,
    "isDefault": true,
    "isSystem": true,
    "customerAssignable": true,
    "createdAt": "string",
    "updatedAt": null,
    "acl": {
      "features": [
        "string"
      ],
      "isPortalAdmin": true
    }
  }
}
401Not authenticated
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
403Insufficient permissions
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
404Role not found
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/customer_accounts/admin/roles/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json"
PUT/customer_accounts/admin/roles/{id}

Update customer role (admin)

Updates a customer role. System roles are protected from name changes.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Request body (application/json)

{}

Responses

200Role updated
Content-Type: application/json
{
  "ok": true
}
400Validation failed or system role restriction
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
401Not authenticated
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
403Insufficient permissions
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
404Role not found
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X PUT "http://108.165.128.56:3000/api/customer_accounts/admin/roles/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{}"
DELETE/customer_accounts/admin/roles/{id}

Delete customer role (admin)

Soft deletes a customer role and its ACL. The default role (auto-assigned to new portal users) and roles with assigned users cannot be deleted.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Role deleted
Content-Type: application/json
{
  "ok": true
}
400Default role or has assigned users
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
401Not authenticated
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
403Insufficient permissions
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
404Role not found
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/customer_accounts/admin/roles/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json"
PUT/customer_accounts/admin/roles/{id}/acl

Update customer role ACL (admin)

Updates the ACL (features and portal admin flag) for a customer role. Invalidates RBAC cache after update.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Request body (application/json)

{
  "features": [
    "string"
  ]
}

Responses

200ACL updated
Content-Type: application/json
{
  "ok": true,
  "updatedAt": "string"
}
400Validation failed
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
401Not authenticated
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
403Insufficient permissions
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
404Role not found
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
409Stale ACL write (optimistic-lock conflict)
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X PUT "http://108.165.128.56:3000/api/customer_accounts/admin/roles/00000000-0000-4000-8000-000000000000/acl" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"features\": [
    \"string\"
  ]
}"
GET/customer_accounts/admin/users

List customer users (admin)

Returns a paginated list of customer users with roles. Supports filtering by status, company, role, and search.

Parameters

NameInRequiredSchemaDescription
pagequeryNoany—
pageSizequeryNoany—
statusqueryNoany—
customerEntityIdqueryNoany—
roleIdqueryNoany—
searchqueryNoany—

Responses

200Paginated user list
Content-Type: application/json
{
  "ok": true,
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "email": "string",
      "displayName": "string",
      "emailVerified": true,
      "isActive": true,
      "lockedUntil": null,
      "lastLoginAt": null,
      "customerEntityId": null,
      "personEntityId": null,
      "createdAt": "string",
      "updatedAt": null,
      "roles": [
        {
          "id": "00000000-0000-4000-8000-000000000000",
          "name": "string",
          "slug": "string"
        }
      ]
    }
  ],
  "total": 1,
  "totalPages": 1,
  "page": 1
}
401Not authenticated
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
403Insufficient permissions
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/customer_accounts/admin/users" \
  -H "Accept: application/json"
POST/customer_accounts/admin/users

Create customer user (admin)

Creates a new customer user directly. Staff-initiated, bypasses signup flow.

Request body (application/json)

{
  "email": "user@example.com",
  "password": "string",
  "displayName": "string"
}

Responses

201User created
Content-Type: application/json
{
  "ok": true,
  "user": {
    "id": "00000000-0000-4000-8000-000000000000",
    "email": "string",
    "displayName": "string"
  }
}
400Validation failed
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
401Not authenticated
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
403Insufficient permissions
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
409Email already exists
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/customer_accounts/admin/users" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"email\": \"user@example.com\",
  \"password\": \"string\",
  \"displayName\": \"string\"
}"
GET/customer_accounts/admin/users-invite

List pending customer invitations (admin)

Lists invitations that are still pending — not accepted, not cancelled, and not expired — for the caller's tenant and organization. The invitation token is never returned.

Parameters

NameInRequiredSchemaDescription
pagequeryNoany—
pageSizequeryNoany—
personEntityIdqueryNoany—
customerEntityIdqueryNoany—
emailqueryNoany—

Responses

200Pending invitations
Content-Type: application/json
{
  "ok": true,
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "email": "string",
      "displayName": null,
      "customerEntityId": null,
      "personEntityId": null,
      "roleIds": [
        "00000000-0000-4000-8000-000000000000"
      ],
      "invitedByUserId": null,
      "expiresAt": "string",
      "createdAt": "string"
    }
  ],
  "total": 1,
  "totalPages": 1,
  "page": 1
}
400Validation failed
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
401Not authenticated
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
403Insufficient permissions
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/customer_accounts/admin/users-invite" \
  -H "Accept: application/json"
POST/customer_accounts/admin/users-invite

Invite customer user (admin)

Creates a staff-initiated invitation for a new customer user. The invitedByUserId is set from the staff auth context.

Request body (application/json)

{
  "email": "user@example.com",
  "roleIds": [
    "00000000-0000-4000-8000-000000000000"
  ]
}

Responses

201Invitation created
Content-Type: application/json
{
  "ok": true,
  "invitation": {
    "id": "00000000-0000-4000-8000-000000000000",
    "email": "string",
    "customerEntityId": null,
    "personEntityId": null,
    "expiresAt": "string"
  }
}
400Validation failed
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
401Not authenticated
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
403Insufficient permissions
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
429Too many invitation requests
Content-Type: application/json
{
  "error": "string"
}
502Invitation email could not be sent
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/customer_accounts/admin/users-invite" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"email\": \"user@example.com\",
  \"roleIds\": [
    \"00000000-0000-4000-8000-000000000000\"
  ]
}"
GET/customer_accounts/admin/users/{id}

Get customer user detail (admin)

Returns full customer user details including CRM links, roles, and active session count.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200User detail
Content-Type: application/json
{
  "ok": true,
  "user": {
    "id": "00000000-0000-4000-8000-000000000000",
    "email": "string",
    "displayName": "string",
    "emailVerified": true,
    "isActive": true,
    "lockedUntil": null,
    "lastLoginAt": null,
    "failedLoginAttempts": 1,
    "customerEntityId": null,
    "personEntityId": null,
    "createdAt": "string",
    "updatedAt": null,
    "roles": [
      {
        "id": "00000000-0000-4000-8000-000000000000",
        "name": "string",
        "slug": "string"
      }
    ],
    "activeSessionCount": 1
  }
}
401Not authenticated
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
403Insufficient permissions
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
404User not found
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/customer_accounts/admin/users/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json"
PUT/customer_accounts/admin/users/{id}

Update customer user (admin)

Updates a customer user. Staff can update status, lock, CRM links, and roles. Role assignment bypasses customer_assignable check.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Request body (application/json)

{
  "lockedUntil": null,
  "personEntityId": null,
  "customerEntityId": null
}

Responses

200User updated
Content-Type: application/json
{
  "ok": true
}
400Validation failed or role not found
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
401Not authenticated
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
403Insufficient permissions
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
404User not found
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X PUT "http://108.165.128.56:3000/api/customer_accounts/admin/users/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"lockedUntil\": null,
  \"personEntityId\": null,
  \"customerEntityId\": null
}"
DELETE/customer_accounts/admin/users/{id}

Delete customer user (admin)

Soft deletes a customer user and revokes all their active sessions.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200User deleted
Content-Type: application/json
{
  "ok": true
}
401Not authenticated
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
403Insufficient permissions
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
404User not found
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/customer_accounts/admin/users/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json"
POST/customer_accounts/admin/users/{id}/reset-password

Reset customer user password (admin)

Allows staff to set a new password for a customer user.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Request body (application/json)

{
  "newPassword": "string"
}

Responses

200Password reset
Content-Type: application/json
{
  "ok": true
}
400Validation failed
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
401Not authenticated
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
403Insufficient permissions
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
404User not found
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/customer_accounts/admin/users/00000000-0000-4000-8000-000000000000/reset-password" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"newPassword\": \"string\"
}"
POST/customer_accounts/admin/users/{id}/send-reset-link

Send password reset link for customer user (admin)

Creates a password reset token for a customer user and returns a reset link URL. The admin must prepend the appropriate portal domain/slug to the relative URL.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Reset link generated
Content-Type: application/json
{
  "ok": true,
  "resetLink": "string"
}
401Not authenticated
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
403Insufficient permissions
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
404User not found
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/customer_accounts/admin/users/00000000-0000-4000-8000-000000000000/send-reset-link" \
  -H "Accept: application/json"
POST/customer_accounts/admin/users/{id}/verify-email

Verify customer user email (admin)

Allows staff to manually mark a customer user email as verified.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Email verified
Content-Type: application/json
{
  "ok": true
}
401Not authenticated
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
403Insufficient permissions
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
404User not found
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/customer_accounts/admin/users/00000000-0000-4000-8000-000000000000/verify-email" \
  -H "Accept: application/json"

CustomerAccounts

Showing 8 of 8 endpoints
GET/customer_accounts/admin/domain-mappings
Auth required

List domain mappings

Returns all custom-domain mappings for the current tenant, optionally filtered by organization.

Responses

200OK
Content-Type: application/json
{
  "ok": true,
  "domainMappings": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "hostname": "string",
      "organizationId": "00000000-0000-4000-8000-000000000000",
      "tenantId": "00000000-0000-4000-8000-000000000000",
      "provider": "traefik",
      "status": "pending",
      "verifiedAt": null,
      "lastDnsCheckAt": null,
      "dnsFailureReason": null,
      "tlsFailureReason": null,
      "tlsRetryCount": 1,
      "cnameTarget": null,
      "aRecordTarget": null,
      "createdAt": "string",
      "updatedAt": null
    }
  ],
  "config": {
    "cnameTarget": null,
    "aRecordTarget": null
  }
}
401Unauthorized
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
403Forbidden
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/customer_accounts/admin/domain-mappings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/customer_accounts/admin/domain-mappings
Auth required

Register a custom domain

Registers a new custom domain mapping for an organization. Verifies via DNS asynchronously.

Request body (application/json)

{
  "hostname": "string",
  "organizationId": "00000000-0000-4000-8000-000000000000"
}

Responses

201Created
Content-Type: application/json
{
  "ok": true,
  "domainMapping": {
    "id": "00000000-0000-4000-8000-000000000000",
    "hostname": "string",
    "organizationId": "00000000-0000-4000-8000-000000000000",
    "tenantId": "00000000-0000-4000-8000-000000000000",
    "provider": "traefik",
    "status": "pending",
    "verifiedAt": null,
    "lastDnsCheckAt": null,
    "dnsFailureReason": null,
    "tlsFailureReason": null,
    "tlsRetryCount": 1,
    "cnameTarget": null,
    "aRecordTarget": null,
    "createdAt": "string",
    "updatedAt": null
  }
}
400Validation error
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
403Forbidden
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
409Conflict
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/customer_accounts/admin/domain-mappings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"hostname\": \"string\",
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\"
}"
DELETE/customer_accounts/admin/domain-mappings
Auth required

Remove a custom domain

Removes the domain mapping identified by ?id=. Cache and Traefik routing drain within TTL.

Responses

200OK
Content-Type: application/json
{
  "ok": true
}
400Bad request
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
403Forbidden
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/customer_accounts/admin/domain-mappings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/customer_accounts/admin/domain-mappings/{id}/health-check
Auth required

Trigger TLS health check

Runs an HTTPS probe to verify Traefik has provisioned a certificate. On success: transitions the mapping to active.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200OK
Content-Type: application/json
{
  "ok": true,
  "domainMapping": {
    "id": "00000000-0000-4000-8000-000000000000",
    "hostname": "string",
    "status": "string",
    "tlsRetryCount": 1,
    "tlsFailureReason": null
  }
}
401Unauthorized
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
403Forbidden
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
404Not found
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/customer_accounts/admin/domain-mappings/:id/health-check" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/customer_accounts/admin/domain-mappings/{id}/verify
Auth required

Trigger DNS verification

Runs DNS verification (CNAME → A → reverse-resolve fallback) for the domain mapping. Returns diagnostics on failure.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200OK — see status
Content-Type: application/json
{
  "ok": true,
  "domainMapping": {
    "id": "00000000-0000-4000-8000-000000000000",
    "hostname": "string",
    "status": "string",
    "verifiedAt": null,
    "lastDnsCheckAt": null,
    "dnsFailureReason": null
  },
  "diagnostics": null
}
401Unauthorized
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
403Forbidden
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
404Not found
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/customer_accounts/admin/domain-mappings/:id/verify" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/customer_accounts/domain-check

Verify a hostname is allowed for TLS provisioning

Called by Traefik before issuing a Let's Encrypt certificate. Requires the X-Domain-Check-Secret header to match DOMAIN_CHECK_SECRET.

Responses

200Hostname allowed
Content-Type: application/json
{
  "ok": true
}
403Forbidden
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
404Hostname not registered or not yet verified
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
503Server misconfiguration
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/customer_accounts/domain-check" \
  -H "Accept: application/json"
GET/customer_accounts/domain-resolve

Single-host resolve for the Node middleware

Internal endpoint used by the portal middleware to populate its in-memory cache. Requires X-Domain-Resolve-Secret header.

Responses

200OK
Content-Type: application/json
{
  "ok": true,
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "orgSlug": null,
  "status": "active"
}
400Bad request
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
403Forbidden
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
404Not found
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
503Server misconfiguration
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/customer_accounts/domain-resolve" \
  -H "Accept: application/json"
GET/customer_accounts/domain-resolve/all

Batch warm-up for the Node middleware

Returns every active domain mapping in a single payload so the middleware can populate its cache on process start. Requires X-Domain-Resolve-Secret header.

Responses

200OK
Content-Type: application/json
{
  "ok": true,
  "domains": [
    {
      "hostname": "string",
      "tenantId": "00000000-0000-4000-8000-000000000000",
      "organizationId": "00000000-0000-4000-8000-000000000000",
      "orgSlug": null,
      "status": "active"
    }
  ]
}
403Forbidden
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
429Too many requests
Content-Type: application/json
{
  "error": "string"
}
503Server misconfiguration
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/customer_accounts/domain-resolve/all" \
  -H "Accept: application/json"

Customer Authentication

Showing 8 of 8 endpoints
POST/customer_accounts/email/verify

Verify customer email address

Validates the email verification token and marks the email as verified.

Request body (application/json)

{
  "token": "string"
}

Responses

200Email verified
Content-Type: application/json
{
  "ok": true
}
400Invalid or expired token
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/customer_accounts/email/verify" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"token\": \"string\"
}"
POST/customer_accounts/invitations/accept

Accept customer invitation

Accepts an invitation, creates the user account, assigns roles, and auto-logs in.

Request body (application/json)

{
  "token": "string",
  "password": "string",
  "displayName": "string"
}

Responses

201Invitation accepted and user created
Content-Type: application/json
{
  "ok": true,
  "user": {
    "id": "00000000-0000-4000-8000-000000000000",
    "email": "user@example.com",
    "displayName": "string",
    "emailVerified": true
  },
  "resolvedFeatures": [
    "string"
  ]
}
400Invalid or expired invitation
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
409An account with this email address already exists
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/customer_accounts/invitations/accept" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"token\": \"string\",
  \"password\": \"string\",
  \"displayName\": \"string\"
}"
POST/customer_accounts/login

Authenticate customer credentials

Validates customer credentials and issues JWT + session cookies.

Request body (application/json)

{
  "email": "user@example.com",
  "password": "string"
}

Responses

200Login successful
Content-Type: application/json
{
  "ok": true,
  "user": {
    "id": "00000000-0000-4000-8000-000000000000",
    "email": "user@example.com",
    "displayName": "string",
    "emailVerified": true
  },
  "resolvedFeatures": [
    "string"
  ]
}
400Validation failed
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
401Invalid credentials
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
429Too many login attempts
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/customer_accounts/login" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"email\": \"user@example.com\",
  \"password\": \"string\"
}"
POST/customer_accounts/magic-link/request

Request magic link login

Sends a magic link to the customer email. Always returns 200 to prevent enumeration.

Request body (application/json)

{
  "email": "user@example.com"
}

Responses

200Request accepted
Content-Type: application/json
{
  "ok": true
}
429Too many requests
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/customer_accounts/magic-link/request" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"email\": \"user@example.com\"
}"
POST/customer_accounts/magic-link/verify

Verify magic link token

Validates the magic link token, auto-verifies email, and creates a session.

Request body (application/json)

{
  "token": "string"
}

Responses

200Login successful
Content-Type: application/json
{
  "ok": true,
  "user": {
    "id": "00000000-0000-4000-8000-000000000000",
    "email": "user@example.com",
    "displayName": "string",
    "emailVerified": true
  },
  "resolvedFeatures": [
    "string"
  ]
}
400Invalid or expired token
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
401Account not found
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/customer_accounts/magic-link/verify" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"token\": \"string\"
}"
POST/customer_accounts/password/reset-confirm

Confirm customer password reset

Validates the reset token and sets a new password. Revokes all existing sessions.

Request body (application/json)

{
  "token": "string",
  "password": "string"
}

Responses

200Password reset successful
Content-Type: application/json
{
  "ok": true
}
400Invalid or expired token
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/customer_accounts/password/reset-confirm" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"token\": \"string\",
  \"password\": \"string\"
}"
POST/customer_accounts/password/reset-request

Request customer password reset

Initiates a password reset flow. Always returns 200 to prevent email enumeration.

Request body (application/json)

{
  "email": "user@example.com"
}

Responses

200Request accepted
Content-Type: application/json
{
  "ok": true
}
429Too many requests
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/customer_accounts/password/reset-request" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"email\": \"user@example.com\"
}"
POST/customer_accounts/signup

Register a new customer account

Accepts a signup request and always returns 202 to prevent account enumeration.

Request body (application/json)

{
  "email": "user@example.com",
  "password": "string",
  "displayName": "string"
}

Responses

202Signup accepted
Content-Type: application/json
{
  "ok": true
}
400Validation failed or invalid request origin
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
429Too many signup attempts
Content-Type: application/json
{
  "error": "string"
}
500Signup email origin is not configured
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/customer_accounts/signup" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"email\": \"user@example.com\",
  \"password\": \"string\",
  \"displayName\": \"string\"
}"

Customer Portal

Showing 19 of 19 endpoints
GET/customer_accounts/portal/events/stream

Subscribe to portal events via SSE (Portal Event Bridge)

Long-lived SSE connection that receives server-side events marked with portalBroadcast: true. Events are filtered by the customer's tenant, organization, and recipient user audience.

Responses

200Event stream (text/event-stream)
Content-Type: application/json
"string"
401Not authenticated
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/customer_accounts/portal/events/stream" \
  -H "Accept: application/json"
POST/customer_accounts/portal/feature-check

Check customer portal feature access

Checks which of the requested features the authenticated customer user has. Used by portal menu injection for feature-gating.

Request body (application/json)

{
  "features": [
    "string"
  ]
}

Responses

200Feature check result
Content-Type: application/json
{
  "ok": true,
  "granted": [
    "string"
  ]
}
400Invalid request
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
401Not authenticated
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/customer_accounts/portal/feature-check" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"features\": [
    \"string\"
  ]
}"
POST/customer_accounts/portal/logout

Customer logout

Revokes the current session and clears authentication cookies.

Responses

200Logged out
Content-Type: application/json
{
  "ok": true
}

Example

curl -X POST "http://108.165.128.56:3000/api/customer_accounts/portal/logout" \
  -H "Accept: application/json"
GET/customer_accounts/portal/nav

Portal sidebar navigation

Returns the portal sidebar for the authenticated customer. Items are derived from each portal page's `nav` metadata and filtered by `requireCustomerFeatures` against concrete effective features.

Responses

200Portal sidebar groups
Content-Type: application/json
{
  "ok": true,
  "orgSlug": "string",
  "groups": [
    {
      "id": "main",
      "items": [
        {
          "id": "string",
          "label": "string",
          "href": "string",
          "order": 1
        }
      ]
    }
  ],
  "grantedFeatures": [
    "string"
  ],
  "isPortalAdmin": true
}
401Not authenticated
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
404Organization not found
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/customer_accounts/portal/nav" \
  -H "Accept: application/json"
GET/customer_accounts/portal/notifications

List customer notifications

Returns paginated notifications for the authenticated customer user. Dismissed notifications are excluded by default unless ?status=dismissed is specified.

Responses

200Notification list
Content-Type: application/json
{
  "ok": true,
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "type": "string",
      "title": "string",
      "body": null,
      "titleKey": null,
      "bodyKey": null,
      "titleVariables": null,
      "bodyVariables": null,
      "icon": null,
      "severity": "info",
      "status": "unread",
      "actions": [
        {
          "id": "string",
          "label": "string"
        }
      ],
      "sourceModule": null,
      "sourceEntityType": null,
      "sourceEntityId": null,
      "linkHref": null,
      "createdAt": "string",
      "readAt": null,
      "actionTaken": null
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1
}
401Not authenticated
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/customer_accounts/portal/notifications" \
  -H "Accept: application/json"
PUT/customer_accounts/portal/notifications/{id}/dismiss

Dismiss notification

Dismisses a single notification for the authenticated customer user.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Notification dismissed
Content-Type: application/json
{
  "ok": true
}
401Not authenticated
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
404Notification not found
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X PUT "http://108.165.128.56:3000/api/customer_accounts/portal/notifications/00000000-0000-4000-8000-000000000000/dismiss" \
  -H "Accept: application/json"
PUT/customer_accounts/portal/notifications/{id}/read

Mark notification as read

Marks a single notification as read for the authenticated customer user.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Notification marked as read
Content-Type: application/json
{
  "ok": true
}
401Not authenticated
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
404Notification not found
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X PUT "http://108.165.128.56:3000/api/customer_accounts/portal/notifications/00000000-0000-4000-8000-000000000000/read" \
  -H "Accept: application/json"
PUT/customer_accounts/portal/notifications/mark-all-read

Mark all notifications as read

Marks all unread notifications as read for the authenticated customer user.

Responses

200All notifications marked as read
Content-Type: application/json
{
  "ok": true,
  "count": 1
}
401Not authenticated
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X PUT "http://108.165.128.56:3000/api/customer_accounts/portal/notifications/mark-all-read" \
  -H "Accept: application/json"
GET/customer_accounts/portal/notifications/unread-count

Get unread notification count

Returns the number of unread notifications for the authenticated customer user.

Responses

200Unread count
Content-Type: application/json
{
  "ok": true,
  "unreadCount": 1
}
401Not authenticated
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/customer_accounts/portal/notifications/unread-count" \
  -H "Accept: application/json"
POST/customer_accounts/portal/password-change

Change customer password

Changes the authenticated customer user password after verifying the current password. Revokes all existing sessions.

Request body (application/json)

{
  "currentPassword": "string",
  "newPassword": "string"
}

Responses

200Password changed
Content-Type: application/json
{
  "ok": true
}
400Current password incorrect or validation failed
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
401Not authenticated
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/customer_accounts/portal/password-change" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"currentPassword\": \"string\",
  \"newPassword\": \"string\"
}"
GET/customer_accounts/portal/profile

Get customer profile

Returns the authenticated customer user profile with roles and permissions.

Responses

200Profile data
Content-Type: application/json
{
  "ok": true,
  "user": {
    "id": "00000000-0000-4000-8000-000000000000",
    "email": "string",
    "displayName": "string",
    "emailVerified": true,
    "customerEntityId": null,
    "personEntityId": null,
    "isActive": true,
    "lastLoginAt": null,
    "createdAt": "string"
  },
  "roles": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "name": "string",
      "slug": "string"
    }
  ],
  "resolvedFeatures": [
    "string"
  ],
  "isPortalAdmin": true
}
401Not authenticated
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/customer_accounts/portal/profile" \
  -H "Accept: application/json"
PUT/customer_accounts/portal/profile

Update customer profile

Updates the authenticated customer user profile.

Request body (application/json)

{}

Responses

200Profile updated
Content-Type: application/json
{
  "ok": true,
  "user": {
    "id": "00000000-0000-4000-8000-000000000000",
    "email": "string",
    "displayName": "string"
  }
}
401Not authenticated
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
403Insufficient permissions
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X PUT "http://108.165.128.56:3000/api/customer_accounts/portal/profile" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{}"
GET/customer_accounts/portal/sessions

List customer sessions

Returns active sessions for the authenticated customer user.

Responses

200Session list
Content-Type: application/json
{
  "ok": true,
  "sessions": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "ipAddress": null,
      "userAgent": null,
      "lastUsedAt": null,
      "createdAt": "string",
      "expiresAt": "string",
      "isCurrent": true
    }
  ]
}
401Not authenticated
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/customer_accounts/portal/sessions" \
  -H "Accept: application/json"
POST/customer_accounts/portal/sessions-refresh

Refresh customer JWT from session token

Uses the session cookie to issue a fresh JWT access token.

Responses

200Token refreshed
Content-Type: application/json
{
  "ok": true,
  "resolvedFeatures": [
    "string"
  ]
}
401Invalid session
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/customer_accounts/portal/sessions-refresh" \
  -H "Accept: application/json"
DELETE/customer_accounts/portal/sessions/{id}

Revoke a customer session

Revokes a specific session (not the current one).

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Session revoked
Content-Type: application/json
{
  "ok": true
}
400Cannot revoke current session
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
401Not authenticated
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
404Session not found
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/customer_accounts/portal/sessions/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json"
GET/customer_accounts/portal/users

List company portal users

Lists portal users associated with the same company. Paginated (default pageSize 25, max 100).

Parameters

NameInRequiredSchemaDescription
pagequeryNoany—
pageSizequeryNoany—

Responses

200Paginated user list
Content-Type: application/json
{
  "ok": true,
  "users": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "email": "string",
      "displayName": "string",
      "emailVerified": true,
      "isActive": true,
      "lastLoginAt": null,
      "createdAt": "string",
      "roles": [
        {
          "id": "00000000-0000-4000-8000-000000000000",
          "name": "string",
          "slug": "string"
        }
      ]
    }
  ],
  "total": 1,
  "totalPages": 1,
  "page": 1,
  "pageSize": 1
}
401Not authenticated
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
403Insufficient permissions
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/customer_accounts/portal/users" \
  -H "Accept: application/json"
POST/customer_accounts/portal/users-invite

Invite a user to the company portal

Creates an invitation for a new user to join the company portal.

Request body (application/json)

{
  "email": "user@example.com",
  "roleIds": [
    "00000000-0000-4000-8000-000000000000"
  ]
}

Responses

201Invitation created
Content-Type: application/json
{
  "ok": true,
  "invitation": {
    "id": "00000000-0000-4000-8000-000000000000",
    "email": "string",
    "expiresAt": "string"
  }
}
400Validation failed
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
401Not authenticated
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
403Insufficient permissions or non-assignable role
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
429Too many invitation requests
Content-Type: application/json
{
  "error": "string"
}
502Invitation email could not be sent
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/customer_accounts/portal/users-invite" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"email\": \"user@example.com\",
  \"roleIds\": [
    \"00000000-0000-4000-8000-000000000000\"
  ]
}"
DELETE/customer_accounts/portal/users/{id}

Delete a company portal user

Soft deletes a portal user and revokes all their sessions.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200User deleted
Content-Type: application/json
{
  "ok": true
}
400Cannot delete self
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
401Not authenticated
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
403Insufficient permissions
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
404User not found
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/customer_accounts/portal/users/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json"
PUT/customer_accounts/portal/users/{id}/roles

Update portal user roles

Assigns new roles to a company portal user.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Request body (application/json)

{
  "roleIds": [
    "00000000-0000-4000-8000-000000000000"
  ]
}

Responses

200Roles updated
Content-Type: application/json
{
  "ok": true
}
400Validation failed
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
401Not authenticated
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
403Insufficient permissions
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}
404User not found
Content-Type: application/json
{
  "ok": false,
  "error": "string"
}

Example

curl -X PUT "http://108.165.128.56:3000/api/customer_accounts/portal/users/00000000-0000-4000-8000-000000000000/roles" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"roleIds\": [
    \"00000000-0000-4000-8000-000000000000\"
  ]
}"

Customers

Showing 20 of 101 endpoints
GET/customers/activities
Auth required

List activitys

Returns a paginated collection of activitys scoped to the authenticated organization.

Parameters

NameInRequiredSchemaDescription
pagequeryNoany—
pageSizequeryNoany—
entityIdqueryNoany—
dealIdqueryNoany—
activityTypequeryNoany—
sortFieldqueryNoany—
sortDirqueryNoany—
idsqueryNoanyComma-separated list of record UUIDs to filter by (max 200).

Responses

200Paginated activitys
Content-Type: application/json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "activityType": "string",
      "subject": null,
      "body": null,
      "occurredAt": null,
      "createdAt": "string",
      "appearanceIcon": null,
      "appearanceColor": null,
      "entityId": null,
      "authorUserId": null,
      "authorName": null,
      "authorEmail": null,
      "dealId": null,
      "dealTitle": null,
      "customValues": null,
      "activityTypeLabel": null
    }
  ],
  "total": 1,
  "totalPages": 1
}

Example

curl -X GET "http://108.165.128.56:3000/api/customers/activities?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/customers/activities
Auth required

Create activity

DEPRECATED (sunset 2026-06-30): Creates a timeline activity. Use POST /api/customers/interactions instead.

Request body (application/json)

{
  "entityId": "00000000-0000-4000-8000-000000000000",
  "activityType": "string",
  "phoneNumber": null,
  "appearanceIcon": null,
  "appearanceColor": null
}

Responses

201Activity created
Content-Type: application/json
{
  "id": null
}

Example

curl -X POST "http://108.165.128.56:3000/api/customers/activities" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"entityId\": \"00000000-0000-4000-8000-000000000000\",
  \"activityType\": \"string\",
  \"phoneNumber\": null,
  \"appearanceIcon\": null,
  \"appearanceColor\": null
}"
PUT/customers/activities
Auth required

Update activity

DEPRECATED (sunset 2026-06-30): Updates an activity. Use PUT /api/customers/interactions instead.

Request body (application/json)

{
  "id": "00000000-0000-4000-8000-000000000000",
  "phoneNumber": null,
  "appearanceIcon": null,
  "appearanceColor": null
}

Responses

200Activity updated
Content-Type: application/json
{
  "ok": true
}

Example

curl -X PUT "http://108.165.128.56:3000/api/customers/activities" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"phoneNumber\": null,
  \"appearanceIcon\": null,
  \"appearanceColor\": null
}"
DELETE/customers/activities
Auth required

Delete activity

DEPRECATED (sunset 2026-06-30): Deletes an activity. Use DELETE /api/customers/interactions instead.

Request body (application/json)

{
  "id": "00000000-0000-4000-8000-000000000000"
}

Responses

200Activity deleted
Content-Type: application/json
{
  "ok": true
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/customers/activities" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
GET/customers/addresses
Auth required

List addresss

Returns a paginated collection of addresss scoped to the authenticated organization.

Parameters

NameInRequiredSchemaDescription
pagequeryNoany—
pageSizequeryNoany—
entityIdqueryNoany—
idqueryNoany—
sortFieldqueryNoany—
sortDirqueryNoany—
idsqueryNoanyComma-separated list of record UUIDs to filter by (max 200).

Responses

200Paginated addresss
Content-Type: application/json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "entity_id": "00000000-0000-4000-8000-000000000000",
      "name": null,
      "purpose": null,
      "company_name": null,
      "address_line1": null,
      "address_line2": null,
      "building_number": null,
      "flat_number": null,
      "city": null,
      "region": null,
      "postal_code": null,
      "country": null,
      "latitude": null,
      "longitude": null,
      "is_primary": null,
      "organization_id": null,
      "tenant_id": null,
      "updated_at": null
    }
  ],
  "total": 1,
  "totalPages": 1
}

Example

curl -X GET "http://108.165.128.56:3000/api/customers/addresses?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/customers/addresses
Auth required

Create address

Creates a customer address record and associates it with the referenced entity.

Request body (application/json)

{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "entityId": "00000000-0000-4000-8000-000000000000",
  "addressLine1": "string",
  "latitude": null,
  "longitude": null
}

Responses

201Address created
Content-Type: application/json
{
  "id": null
}

Example

curl -X POST "http://108.165.128.56:3000/api/customers/addresses" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"entityId\": \"00000000-0000-4000-8000-000000000000\",
  \"addressLine1\": \"string\",
  \"latitude\": null,
  \"longitude\": null
}"
PUT/customers/addresses
Auth required

Update address

Updates fields on an existing customer address.

Request body (application/json)

{
  "id": "00000000-0000-4000-8000-000000000000",
  "latitude": null,
  "longitude": null
}

Responses

200Address updated
Content-Type: application/json
{
  "ok": true
}

Example

curl -X PUT "http://108.165.128.56:3000/api/customers/addresses" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"latitude\": null,
  \"longitude\": null
}"
DELETE/customers/addresses
Auth required

Delete address

Deletes an address by id. The identifier may be included in the body or query.

Request body (application/json)

{
  "id": "00000000-0000-4000-8000-000000000000"
}

Responses

200Address deleted
Content-Type: application/json
{
  "ok": true
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/customers/addresses" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
GET/customers/assignable-staff
Auth required

DEPRECATED: use GET /api/staff/team-members/assignable instead.

Deprecated. Returns 308 Permanent Redirect to /api/staff/team-members/assignable preserving the query string. Will be removed no earlier than the next major release.

Parameters

NameInRequiredSchemaDescription
pagequeryNoany—
pageSizequeryNoany—
searchqueryNoany—

Responses

200Assignable staff members (only reachable by following the redirect).
Content-Type: application/json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "teamMemberId": "00000000-0000-4000-8000-000000000000",
      "userId": "00000000-0000-4000-8000-000000000000",
      "displayName": "string",
      "email": null,
      "teamName": null,
      "user": null,
      "team": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
308Permanent redirect to /api/staff/team-members/assignable.
Content-Type: application/json
{
  "error": "string"
}
400Invalid request
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
403Forbidden
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/customers/assignable-staff?page=1&pageSize=24" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/customers/comments
Auth required

List comments

Returns a paginated collection of comments scoped to the authenticated organization.

Parameters

NameInRequiredSchemaDescription
pagequeryNoany—
pageSizequeryNoany—
entityIdqueryNoany—
dealIdqueryNoany—
sortFieldqueryNoany—
sortDirqueryNoany—
idsqueryNoanyComma-separated list of record UUIDs to filter by (max 200).

Responses

200Paginated comments
Content-Type: application/json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "entity_id": null,
      "deal_id": null,
      "body": null,
      "author_user_id": null,
      "appearance_icon": null,
      "appearance_color": null,
      "organization_id": null,
      "tenant_id": null,
      "created_at": null,
      "updated_at": null
    }
  ],
  "total": 1,
  "totalPages": 1
}

Example

curl -X GET "http://108.165.128.56:3000/api/customers/comments?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/customers/comments
Auth required

Create comment

Adds a comment to a customer timeline.

Request body (application/json)

{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "entityId": "00000000-0000-4000-8000-000000000000",
  "body": "string",
  "appearanceIcon": null,
  "appearanceColor": null
}

Responses

201Comment created
Content-Type: application/json
{
  "id": null,
  "authorUserId": null
}

Example

curl -X POST "http://108.165.128.56:3000/api/customers/comments" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"entityId\": \"00000000-0000-4000-8000-000000000000\",
  \"body\": \"string\",
  \"appearanceIcon\": null,
  \"appearanceColor\": null
}"
PUT/customers/comments
Auth required

Update comment

Updates an existing timeline comment.

Request body (application/json)

{
  "id": "00000000-0000-4000-8000-000000000000",
  "appearanceIcon": null,
  "appearanceColor": null
}

Responses

200Comment updated
Content-Type: application/json
{
  "ok": true
}

Example

curl -X PUT "http://108.165.128.56:3000/api/customers/comments" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"appearanceIcon\": null,
  \"appearanceColor\": null
}"
DELETE/customers/comments
Auth required

Delete comment

Deletes a comment identified by `id` supplied via body or query string.

Request body (application/json)

{
  "id": "00000000-0000-4000-8000-000000000000"
}

Responses

200Comment deleted
Content-Type: application/json
{
  "ok": true
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/customers/comments" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
GET/customers/companies
Auth required

List companies

Returns a paginated collection of companies scoped to the authenticated organization.

Parameters

NameInRequiredSchemaDescription
pagequeryNoany—
pageSizequeryNoany—
searchqueryNoany—
emailqueryNoany—
emailStartsWithqueryNoany—
emailContainsqueryNoany—
sortFieldqueryNoany—
sortDirqueryNoany—
statusqueryNoany—
lifecycleStagequeryNoany—
sourcequeryNoany—
hasEmailqueryNoany—
hasPhonequeryNoany—
hasNextInteractionqueryNoany—
createdFromqueryNoany—
createdToqueryNoany—
idqueryNoany—
tagIdsqueryNoany—
tagIdsEmptyqueryNoany—
excludeIdsqueryNoany—
excludeLinkedPersonIdqueryNoany—
excludeLinkedCompanyIdqueryNoany—
excludeLinkedDealIdqueryNoany—
idsqueryNoanyComma-separated list of record UUIDs to filter by (max 200).

Responses

200Paginated companies
Content-Type: application/json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "description": null,
      "owner_user_id": null,
      "primary_email": null,
      "primary_phone": null,
      "status": null,
      "lifecycle_stage": null,
      "source": null,
      "next_interaction_at": null,
      "next_interaction_name": null,
      "next_interaction_ref_id": null,
      "next_interaction_icon": null,
      "next_interaction_color": null,
      "organization_id": null,
      "tenant_id": null,
      "created_at": null
    }
  ],
  "total": 1,
  "totalPages": 1
}

Example

curl -X GET "http://108.165.128.56:3000/api/customers/companies?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/customers/companies
Auth required

Create company

Creates a company record and associated profile data.

Request body (application/json)

{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "displayName": "string",
  "description": null,
  "primaryEmail": null,
  "primaryPhone": null,
  "nextInteraction": null,
  "legalName": null,
  "brandName": null,
  "domain": null,
  "websiteUrl": null,
  "sizeBucket": null,
  "annualRevenue": null
}

Responses

201Company created
Content-Type: application/json
{
  "id": null,
  "companyId": null
}

Example

curl -X POST "http://108.165.128.56:3000/api/customers/companies" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"displayName\": \"string\",
  \"description\": null,
  \"primaryEmail\": null,
  \"primaryPhone\": null,
  \"nextInteraction\": null,
  \"legalName\": null,
  \"brandName\": null,
  \"domain\": null,
  \"websiteUrl\": null,
  \"sizeBucket\": null,
  \"annualRevenue\": null
}"
PUT/customers/companies
Auth required

Update company

Updates company profile fields, tags, or custom attributes.

Request body (application/json)

{
  "id": "00000000-0000-4000-8000-000000000000",
  "description": null,
  "primaryEmail": null,
  "primaryPhone": null,
  "nextInteraction": null,
  "legalName": null,
  "brandName": null,
  "domain": null,
  "websiteUrl": null,
  "sizeBucket": null,
  "annualRevenue": null
}

Responses

200Company updated
Content-Type: application/json
{
  "ok": true
}

Example

curl -X PUT "http://108.165.128.56:3000/api/customers/companies" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"description\": null,
  \"primaryEmail\": null,
  \"primaryPhone\": null,
  \"nextInteraction\": null,
  \"legalName\": null,
  \"brandName\": null,
  \"domain\": null,
  \"websiteUrl\": null,
  \"sizeBucket\": null,
  \"annualRevenue\": null
}"
DELETE/customers/companies
Auth required

Delete company

Deletes a company by id. The identifier can be provided via body or query.

Request body (application/json)

{
  "id": "00000000-0000-4000-8000-000000000000"
}

Responses

200Company deleted
Content-Type: application/json
{
  "ok": true
}
422Company has dependent records (people, deals, or direct staff); unlink or reassign before delete.
Content-Type: application/json
{
  "error": "string",
  "code": "COMPANY_HAS_DEPENDENTS"
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/customers/companies" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
GET/customers/companies/{id}
Auth required

Fetch company with related data

Returns a company customer record with optional related resources such as addresses, comments, activities, interactions, deals, todos, and linked people.

Parameters

NameInRequiredSchemaDescription
idpathYesany—
includequeryNoanyComma-separated list of relations to include (addresses, comments, activities, interactions, deals, todos, people).

Responses

200Company detail payload
Content-Type: application/json
{
  "interactionMode": "canonical",
  "company": {
    "id": "00000000-0000-4000-8000-000000000000",
    "displayName": null,
    "description": null,
    "ownerUserId": null,
    "primaryEmail": null,
    "primaryPhone": null,
    "status": null,
    "lifecycleStage": null,
    "source": null,
    "nextInteractionAt": null,
    "nextInteractionName": null,
    "nextInteractionRefId": null,
    "nextInteractionIcon": null,
    "nextInteractionColor": null,
    "organizationId": null,
    "tenantId": null,
    "temperature": null,
    "renewalQuarter": null,
    "createdAt": "string",
    "updatedAt": "string"
  },
  "profile": null,
  "customFields": {},
  "tags": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "label": "string",
      "color": null
    }
  ],
  "addresses": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "name": null,
      "purpose": null,
      "addressLine1": null,
      "addressLine2": null,
      "buildingNumber": null,
      "flatNumber": null,
      "city": null,
      "region": null,
      "postalCode": null,
      "country": null,
      "latitude": null,
      "longitude": null,
      "isPrimary": null,
      "createdAt": "string"
    }
  ],
  "comments": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "body": null,
      "authorUserId": null,
      "authorName": null,
      "authorEmail": null,
      "dealId": null,
      "createdAt": "string",
      "appearanceIcon": null,
      "appearanceColor": null
    }
  ],
  "activities": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "activityType": "string",
      "subject": null,
      "body": null,
      "occurredAt": null,
      "dealId": null,
      "authorUserId": null,
      "authorName": null,
      "authorEmail": null,
      "createdAt": "string",
      "appearanceIcon": null,
      "appearanceColor": null
    }
  ],
  "interactions": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "entityId": null,
      "interactionType": "string",
      "title": null,
      "body": null,
      "status": "string",
      "scheduledAt": null,
      "occurredAt": null,
      "priority": null,
      "authorUserId": null,
      "ownerUserId": null,
      "dealId": null,
      "organizationId": null,
      "tenantId": null,
      "authorName": null,
      "authorEmail": null,
      "dealTitle": null,
      "customValues": null,
      "appearanceIcon": null,
      "appearanceColor": null,
      "source": null,
      "createdAt": "string",
      "updatedAt": "string"
    }
  ],
  "deals": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "title": null,
      "status": null,
      "pipelineStage": null,
      "valueAmount": null,
      "valueCurrency": null,
      "probability": null,
      "expectedCloseAt": null,
      "ownerUserId": null,
      "source": null,
      "createdAt": "string",
      "updatedAt": "string"
    }
  ],
  "todos": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "todoId": "00000000-0000-4000-8000-000000000000",
      "todoSource": "string",
      "createdAt": "string",
      "createdByUserId": null,
      "title": null,
      "isDone": null,
      "priority": null,
      "severity": null,
      "description": null,
      "dueAt": null,
      "todoOrganizationId": null,
      "customValues": null
    }
  ],
  "people": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "displayName": null,
      "primaryEmail": null,
      "primaryPhone": null,
      "status": null,
      "lifecycleStage": null,
      "jobTitle": null,
      "department": null,
      "createdAt": "string",
      "organizationId": null,
      "source": null,
      "temperature": null,
      "linkedAt": null
    }
  ],
  "viewer": {
    "userId": null,
    "name": null,
    "email": null
  }
}
400Invalid identifier
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
403Forbidden — caller lacks the required feature
Content-Type: application/json
{
  "error": "string"
}
404Company not found, or its organization is not in the caller’s scope
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/customers/companies/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/customers/companies/{id}/people
Auth required

List linked people for a company

Parameters

NameInRequiredSchemaDescription
idpathYesany—
pagequeryNoany—
pageSizequeryNoany—
searchqueryNoany—
sortqueryNoany—

Responses

200Paginated linked people
Content-Type: application/json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "displayName": "string",
      "primaryEmail": null,
      "primaryPhone": null,
      "status": null,
      "lifecycleStage": null,
      "jobTitle": null,
      "department": null,
      "createdAt": "string",
      "organizationId": null,
      "temperature": null,
      "source": null,
      "linkedAt": null
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}

Example

curl -X GET "http://108.165.128.56:3000/api/customers/companies/:id/people?page=1&pageSize=20&sort=name-asc" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/customers/companies/{id}/roles
Auth required

List roles for a company

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Role assignments
Content-Type: application/json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "entityType": "company",
      "entityId": "00000000-0000-4000-8000-000000000000",
      "userId": "00000000-0000-4000-8000-000000000000",
      "userName": null,
      "userEmail": null,
      "userPhone": null,
      "roleType": "string",
      "createdAt": "string",
      "updatedAt": "string"
    }
  ]
}
400Invalid request
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/customers/companies/00000000-0000-4000-8000-000000000000/roles" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"

Dashboards

Showing 10 of 10 endpoints
GET/dashboards/layout
Auth required

Load the current dashboard layout

Returns the saved widget layout together with the widgets the current user is allowed to place.

Responses

200Current dashboard layout and available widgets.
Content-Type: application/json
{
  "layout": {
    "items": [
      {
        "id": "00000000-0000-4000-8000-000000000000",
        "widgetId": "string",
        "order": 1
      }
    ]
  },
  "allowedWidgetIds": [
    "string"
  ],
  "canConfigure": true,
  "context": {
    "userId": "00000000-0000-4000-8000-000000000000",
    "tenantId": null,
    "organizationId": null,
    "userName": null,
    "userEmail": null,
    "userLabel": "string"
  },
  "widgets": [
    {
      "id": "string",
      "title": "string",
      "description": null,
      "defaultSize": "sm",
      "defaultEnabled": true,
      "defaultSettings": null,
      "features": [
        "string"
      ],
      "moduleId": "string",
      "icon": null,
      "loaderKey": "string",
      "supportsRefresh": true
    }
  ]
}
401Authentication required
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/dashboards/layout" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
PUT/dashboards/layout
Auth required

Persist dashboard layout changes

Saves the provided widget ordering, sizes, and settings for the current user.

Request body (application/json)

{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "widgetId": "string",
      "order": 1
    }
  ]
}

Responses

200Layout updated successfully.
Content-Type: application/json
{
  "ok": true
}
400Invalid layout payload
Content-Type: application/json
{
  "error": "string"
}
401Authentication required
Content-Type: application/json
{
  "error": "string"
}
403Missing dashboards.configure feature
Content-Type: application/json
{
  "error": "string"
}
503Widget registry unavailable — the layout was not saved
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X PUT "http://108.165.128.56:3000/api/dashboards/layout" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"items\": [
    {
      \"id\": \"00000000-0000-4000-8000-000000000000\",
      \"widgetId\": \"string\",
      \"order\": 1
    }
  ]
}"
PATCH/dashboards/layout/{itemId}
Auth required

Update a dashboard layout item

Adjusts the size or settings for a single widget within the dashboard layout.

Parameters

NameInRequiredSchemaDescription
itemIdpathYesany—

Request body (application/json)

{}

Responses

200Layout item updated.
Content-Type: application/json
{
  "ok": true
}
400Invalid payload or missing item id
Content-Type: application/json
{
  "error": "string"
}
401Authentication required
Content-Type: application/json
{
  "error": "string"
}
403Missing dashboards.configure feature
Content-Type: application/json
{
  "error": "string"
}
404Item not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X PATCH "http://108.165.128.56:3000/api/dashboards/layout/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{}"
GET/dashboards/roles/widgets
Auth required

Fetch widget assignments for a role

Returns the widgets explicitly assigned to the given role together with the evaluation scope.

Parameters

NameInRequiredSchemaDescription
roleIdqueryYesany—
tenantIdqueryNoany—
organizationIdqueryNoany—

Responses

200Current widget configuration for the role.
Content-Type: application/json
{
  "widgetIds": [
    "string"
  ],
  "hasCustom": true,
  "scope": {
    "tenantId": null,
    "organizationId": null
  }
}
400Missing role identifier
Content-Type: application/json
{
  "error": "string"
}
401Authentication required
Content-Type: application/json
{
  "error": "string"
}
403Insufficient permissions to manage role widgets
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/dashboards/roles/widgets?roleId=00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
PUT/dashboards/roles/widgets
Auth required

Update widgets assigned to a role

Persists the widget list for a role within the provided tenant and organization scope.

Request body (application/json)

{
  "roleId": "00000000-0000-4000-8000-000000000000",
  "widgetIds": [
    "string"
  ]
}

Responses

200Widgets updated successfully.
Content-Type: application/json
{
  "ok": true,
  "widgetIds": [
    "string"
  ]
}
400Invalid payload or unknown widgets
Content-Type: application/json
{
  "error": "string"
}
401Authentication required
Content-Type: application/json
{
  "error": "string"
}
403Insufficient permissions to manage role widgets
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X PUT "http://108.165.128.56:3000/api/dashboards/roles/widgets" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"roleId\": \"00000000-0000-4000-8000-000000000000\",
  \"widgetIds\": [
    \"string\"
  ]
}"
GET/dashboards/users/widgets
Auth required

Read widget overrides for a user

Returns the widgets inherited and explicitly configured for the requested user within the current scope.

Parameters

NameInRequiredSchemaDescription
userIdqueryYesany—
tenantIdqueryNoany—
organizationIdqueryNoany—

Responses

200Widget settings for the user.
Content-Type: application/json
{
  "mode": "inherit",
  "widgetIds": [
    "string"
  ],
  "hasCustom": true,
  "effectiveWidgetIds": [
    "string"
  ],
  "scope": {
    "tenantId": null,
    "organizationId": null
  }
}
400Missing user identifier
Content-Type: application/json
{
  "error": "string"
}
401Authentication required
Content-Type: application/json
{
  "error": "string"
}
403Insufficient permissions to manage user widgets
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/dashboards/users/widgets?userId=00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
PUT/dashboards/users/widgets
Auth required

Update user-specific dashboard widgets

Sets the widget override mode and allowed widgets for a user. Passing `mode: inherit` clears overrides.

Request body (application/json)

{
  "userId": "00000000-0000-4000-8000-000000000000",
  "mode": "inherit",
  "widgetIds": [
    "string"
  ]
}

Responses

200Overrides saved.
Content-Type: application/json
{
  "ok": true,
  "mode": "inherit",
  "widgetIds": [
    "string"
  ]
}
400Invalid payload or unknown widgets
Content-Type: application/json
{
  "error": "string"
}
401Authentication required
Content-Type: application/json
{
  "error": "string"
}
403Insufficient permissions to manage user widgets
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X PUT "http://108.165.128.56:3000/api/dashboards/users/widgets" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"userId\": \"00000000-0000-4000-8000-000000000000\",
  \"mode\": \"inherit\",
  \"widgetIds\": [
    \"string\"
  ]
}"
GET/dashboards/widgets/catalog
Auth required

List available dashboard widgets

Returns the catalog of widgets that modules expose, including defaults and feature requirements.

Responses

200Widgets available for assignment.
Content-Type: application/json
{
  "items": [
    {
      "id": "string",
      "title": "string",
      "description": null,
      "defaultSize": "sm",
      "defaultEnabled": true,
      "defaultSettings": null,
      "features": [
        "string"
      ],
      "moduleId": "string",
      "icon": null,
      "loaderKey": "string",
      "supportsRefresh": true
    }
  ]
}
401Authentication required
Content-Type: application/json
{
  "error": "string"
}
403Insufficient permissions to view widget catalog
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/dashboards/widgets/catalog" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/dashboards/widgets/data
Auth required

Fetch aggregated data for dashboard widgets

Executes an aggregation query against the specified entity type and returns the result. Supports date range filtering, grouping, and period-over-period comparison.

Request body (application/json)

{
  "entityType": "string",
  "metric": {
    "field": "string",
    "aggregate": "count"
  }
}

Responses

200Aggregated data for the widget.
Content-Type: application/json
{
  "value": null,
  "data": [
    {
      "value": null
    }
  ],
  "metadata": {
    "fetchedAt": "string",
    "recordCount": 1,
    "currency": null
  }
}
400Invalid request payload
Content-Type: application/json
{
  "error": "string"
}
401Authentication required
Content-Type: application/json
{
  "error": "string"
}
403Missing analytics.view feature
Content-Type: application/json
{
  "error": "string"
}
422Too many rows to group an encrypted field in application code
Content-Type: application/json
{
  "error": "string"
}
500Internal server error
Content-Type: application/json
{
  "error": "string"
}
503Encryption is configured but the group source cannot currently be resolved
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/dashboards/widgets/data" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"entityType\": \"string\",
  \"metric\": {
    \"field\": \"string\",
    \"aggregate\": \"count\"
  }
}"
POST/dashboards/widgets/data/batch
Auth required

Fetch aggregated data for multiple dashboard widgets in one request

Resolves a batch of widget data requests with a single authentication, RBAC, organization-scope, and database-context setup. Each request is keyed by an opaque widget id and resolved independently, so a failure in one widget does not fail the batch.

Request body (application/json)

{
  "requests": [
    {
      "id": "string",
      "request": {
        "entityType": "string",
        "metric": {
          "field": "string",
          "aggregate": "count"
        }
      }
    }
  ]
}

Responses

200Per-widget aggregation results keyed by request id.
Content-Type: application/json
{
  "results": [
    {
      "id": "string",
      "ok": true,
      "data": {
        "value": null,
        "data": [
          {
            "value": null
          }
        ],
        "metadata": {
          "fetchedAt": "string",
          "recordCount": 1,
          "currency": null
        }
      }
    }
  ]
}
400Invalid request payload
Content-Type: application/json
{
  "error": "string"
}
401Authentication required
Content-Type: application/json
{
  "error": "string"
}
500Internal server error
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/dashboards/widgets/data/batch" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"requests\": [
    {
      \"id\": \"string\",
      \"request\": {
        \"entityType\": \"string\",
        \"metric\": {
          \"field\": \"string\",
          \"aggregate\": \"count\"
        }
      }
    }
  ]
}"

Dictionaries

Showing 11 of 11 endpoints
GET/dictionaries
Auth required

List dictionaries

Returns dictionaries accessible to the current organization, optionally including inactive records.

Parameters

NameInRequiredSchemaDescription
includeInactivequeryNoany—

Responses

200Dictionary collection.
Content-Type: application/json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "key": "string",
      "name": "string",
      "description": null,
      "isSystem": true,
      "isActive": true,
      "managerVisibility": null,
      "organizationId": null,
      "createdAt": "string",
      "updatedAt": null
    }
  ]
}
401Authentication required
Content-Type: application/json
{
  "error": "string"
}
500Failed to load dictionaries
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/dictionaries" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/dictionaries
Auth required

Create dictionary

Registers a dictionary scoped to the current organization.

Request body (application/json)

{
  "key": "string",
  "name": "string"
}

Responses

201Dictionary created.
Content-Type: application/json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "key": "string",
  "name": "string",
  "description": null,
  "isSystem": true,
  "isActive": true,
  "managerVisibility": null,
  "organizationId": null,
  "createdAt": "string",
  "updatedAt": null
}
400Validation failed
Content-Type: application/json
{
  "error": "string"
}
401Authentication required
Content-Type: application/json
{
  "error": "string"
}
409Dictionary key already exists
Content-Type: application/json
{
  "error": "string"
}
500Failed to create dictionary
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/dictionaries" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"key\": \"string\",
  \"name\": \"string\"
}"
GET/dictionaries/{dictionaryId}
Auth required

Get dictionary

Returns details for the specified dictionary, including inheritance flags.

Parameters

NameInRequiredSchemaDescription
dictionaryIdpathYesany—

Responses

200Dictionary details.
Content-Type: application/json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "key": "string",
  "name": "string",
  "description": null,
  "isSystem": true,
  "isActive": true,
  "managerVisibility": null,
  "organizationId": null,
  "createdAt": "string",
  "updatedAt": null
}
400Invalid parameters
Content-Type: application/json
{
  "error": "string"
}
401Authentication required
Content-Type: application/json
{
  "error": "string"
}
404Dictionary not found
Content-Type: application/json
{
  "error": "string"
}
500Failed to load dictionary
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/dictionaries/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
PATCH/dictionaries/{dictionaryId}
Auth required

Update dictionary

Updates mutable attributes of the dictionary. Currency dictionaries are protected from modification.

Parameters

NameInRequiredSchemaDescription
dictionaryIdpathYesany—

Request body (application/json)

{}

Responses

200Dictionary updated.
Content-Type: application/json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "key": "string",
  "name": "string",
  "description": null,
  "isSystem": true,
  "isActive": true,
  "managerVisibility": null,
  "organizationId": null,
  "createdAt": "string",
  "updatedAt": null
}
400Validation failed or protected dictionary
Content-Type: application/json
{
  "error": "string"
}
401Authentication required
Content-Type: application/json
{
  "error": "string"
}
404Dictionary not found
Content-Type: application/json
{
  "error": "string"
}
409Dictionary key already exists
Content-Type: application/json
{
  "error": "string"
}
500Failed to update dictionary
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X PATCH "http://108.165.128.56:3000/api/dictionaries/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{}"
DELETE/dictionaries/{dictionaryId}
Auth required

Delete dictionary

Soft deletes the dictionary unless it is the protected currency dictionary.

Parameters

NameInRequiredSchemaDescription
dictionaryIdpathYesany—

Responses

200Dictionary archived.
Content-Type: application/json
{
  "ok": true
}
400Protected dictionary cannot be deleted
Content-Type: application/json
{
  "error": "string"
}
401Authentication required
Content-Type: application/json
{
  "error": "string"
}
404Dictionary not found
Content-Type: application/json
{
  "error": "string"
}
500Failed to delete dictionary
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/dictionaries/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/dictionaries/{dictionaryId}/entries
Auth required

List dictionary entries

Returns entries for the specified dictionary ordered by its configured entry sort mode. The number of entries returned per request is capped at 500; use `limit` and `offset` with the `total`/`hasMore` response fields to page through larger dictionaries.

Parameters

NameInRequiredSchemaDescription
dictionaryIdpathYesany—
limitqueryNoanyMaximum entries to return. Defaults to and is capped at 500.
offsetqueryNoanyNumber of entries to skip. Defaults to 0.

Responses

200Dictionary entries.
Content-Type: application/json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "value": "string",
      "label": "string",
      "color": null,
      "icon": null,
      "position": 1,
      "isDefault": true,
      "createdAt": "string",
      "updatedAt": null
    }
  ],
  "total": 1,
  "limit": 1,
  "offset": 1,
  "hasMore": true,
  "sortMode": "label_asc"
}
400Invalid parameters
Content-Type: application/json
{
  "error": "string"
}
401Authentication required
Content-Type: application/json
{
  "error": "string"
}
404Dictionary not found
Content-Type: application/json
{
  "error": "string"
}
500Failed to load dictionary entries
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/dictionaries/00000000-0000-4000-8000-000000000000/entries" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/dictionaries/{dictionaryId}/entries
Auth required

Create dictionary entry

Creates a new entry in the specified dictionary.

Parameters

NameInRequiredSchemaDescription
dictionaryIdpathYesany—

Request body (application/json)

{
  "value": "string",
  "color": null,
  "icon": null
}

Responses

201Dictionary entry created.
Content-Type: application/json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "value": "string",
  "label": "string",
  "color": null,
  "icon": null,
  "position": 1,
  "isDefault": true,
  "createdAt": "string",
  "updatedAt": null
}
400Validation failed
Content-Type: application/json
{
  "error": "string"
}
401Authentication required
Content-Type: application/json
{
  "error": "string"
}
404Dictionary not found
Content-Type: application/json
{
  "error": "string"
}
500Failed to create dictionary entry
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/dictionaries/00000000-0000-4000-8000-000000000000/entries" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"value\": \"string\",
  \"color\": null,
  \"icon\": null
}"
PATCH/dictionaries/{dictionaryId}/entries/{entryId}
Auth required

Update dictionary entry

Updates the specified dictionary entry using the command bus pipeline.

Parameters

NameInRequiredSchemaDescription
dictionaryIdpathYesany—
entryIdpathYesany—

Request body (application/json)

{
  "color": null,
  "icon": null
}

Responses

200Dictionary entry updated.
Content-Type: application/json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "value": "string",
  "label": "string",
  "color": null,
  "icon": null,
  "position": 1,
  "isDefault": true,
  "createdAt": "string",
  "updatedAt": null
}
400Validation failed
Content-Type: application/json
{
  "error": "string"
}
401Authentication required
Content-Type: application/json
{
  "error": "string"
}
404Dictionary or entry not found
Content-Type: application/json
{
  "error": "string"
}
500Failed to update entry
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X PATCH "http://108.165.128.56:3000/api/dictionaries/00000000-0000-4000-8000-000000000000/entries/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"color\": null,
  \"icon\": null
}"
DELETE/dictionaries/{dictionaryId}/entries/{entryId}
Auth required

Delete dictionary entry

Deletes the specified dictionary entry via the command bus.

Parameters

NameInRequiredSchemaDescription
dictionaryIdpathYesany—
entryIdpathYesany—

Responses

200Entry deleted.
Content-Type: application/json
{
  "ok": true
}
400Validation failed
Content-Type: application/json
{
  "error": "string"
}
401Authentication required
Content-Type: application/json
{
  "error": "string"
}
404Dictionary or entry not found
Content-Type: application/json
{
  "error": "string"
}
500Failed to delete entry
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/dictionaries/00000000-0000-4000-8000-000000000000/entries/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/dictionaries/{dictionaryId}/entries/reorder
Auth required

Reorder dictionary entries

Updates the position of dictionary entries for drag-and-drop reordering.

Parameters

NameInRequiredSchemaDescription
dictionaryIdpathYesany—

Request body (application/json)

{
  "entries": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "position": 1
    }
  ]
}

Responses

200Entries reordered.
Content-Type: application/json
{
  "ok": true
}
400Validation failed
Content-Type: application/json
{
  "error": "string"
}
401Authentication required
Content-Type: application/json
{
  "error": "string"
}
404Dictionary not found
Content-Type: application/json
{
  "error": "string"
}
500Failed to reorder entries
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/dictionaries/00000000-0000-4000-8000-000000000000/entries/reorder" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"entries\": [
    {
      \"id\": \"00000000-0000-4000-8000-000000000000\",
      \"position\": 1
    }
  ]
}"
POST/dictionaries/{dictionaryId}/entries/set-default
Auth required

Set default dictionary entry

Marks the specified entry as the default for this dictionary, clearing any previous default.

Parameters

NameInRequiredSchemaDescription
dictionaryIdpathYesany—

Request body (application/json)

{
  "entryId": "00000000-0000-4000-8000-000000000000"
}

Responses

200Default entry set.
Content-Type: application/json
{
  "ok": true
}
400Validation failed
Content-Type: application/json
{
  "error": "string"
}
401Authentication required
Content-Type: application/json
{
  "error": "string"
}
404Dictionary or entry not found
Content-Type: application/json
{
  "error": "string"
}
500Failed to set default entry
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/dictionaries/00000000-0000-4000-8000-000000000000/entries/set-default" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"entryId\": \"00000000-0000-4000-8000-000000000000\"
}"

Directory

Showing 11 of 11 endpoints
GET/directory/organization-branding
Auth required

Read sidebar branding for the selected organization

Returns the logo URL used by the backend sidebar for the currently selected organization.

Responses

200Organization branding
Content-Type: application/json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "organizationName": "string",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "logoUrl": null,
  "logoPreserveAspectRatio": true,
  "updatedAt": null
}
400A concrete organization scope is required
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
404Organization not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/directory/organization-branding" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
PUT/directory/organization-branding
Auth required

Update sidebar branding for the selected organization

Stores an external image URL or an internal attachment image URL as the selected organization logo.

Request body (application/json)

{
  "logoUrl": null
}

Responses

200Updated organization branding
Content-Type: application/json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "organizationName": "string",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "logoUrl": null,
  "logoPreserveAspectRatio": true,
  "updatedAt": null
}
400Save failed
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
409Organization branding changed since it was loaded
Content-Type: application/json
{
  "error": "string"
}
422Invalid logo URL
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X PUT "http://108.165.128.56:3000/api/directory/organization-branding" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"logoUrl\": null
}"
GET/directory/organization-switcher
Auth required

Load organization switcher menu

Returns the hierarchical menu of organizations the current user may switch to within the active tenant.

Responses

200Organization switcher payload.
Content-Type: application/json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "name": "string",
      "depth": 1,
      "selectable": true,
      "children": []
    }
  ],
  "selectedId": null,
  "canManage": true,
  "canViewAllOrganizations": true,
  "tenantId": null,
  "tenants": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "name": "string",
      "isActive": true
    }
  ],
  "isSuperAdmin": true
}
401Authentication required
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/directory/organization-switcher" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/directory/organizations
Auth required

List organizations

Returns organizations using options, tree, or paginated manage view depending on the `view` parameter.

Parameters

NameInRequiredSchemaDescription
pagequeryNoany—
pageSizequeryNoany—
searchqueryNoany—
viewqueryNoany—
idsqueryNoany—
tenantIdqueryNoany—
includeInactivequeryNoany—
statusqueryNoany—

Responses

200Organization data for the requested view.
Content-Type: application/json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "name": "string",
      "parentId": null,
      "parentName": null,
      "tenantId": null,
      "tenantName": null,
      "rootId": null,
      "treePath": null
    }
  ]
}
400Invalid query or tenant scope
Content-Type: application/json
{
  "error": "string"
}
401Authentication required
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/directory/organizations?page=1&pageSize=50&view=options" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/directory/organizations
Auth required

Create organization

Creates a new organization within a tenant and optionally assigns hierarchy relationships.

Request body (application/json)

{
  "name": "string",
  "slug": null,
  "logoUrl": null,
  "parentId": null
}

Responses

201Organization created.
Content-Type: application/json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
400Validation failed
Content-Type: application/json
{
  "error": "string"
}
401Authentication required
Content-Type: application/json
{
  "error": "string"
}
403Missing directory.organizations.manage feature
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/directory/organizations" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"name\": \"string\",
  \"slug\": null,
  \"logoUrl\": null,
  \"parentId\": null
}"
PUT/directory/organizations
Auth required

Update organization

Updates organization details and hierarchy assignments.

Request body (application/json)

{
  "id": "00000000-0000-4000-8000-000000000000",
  "slug": null,
  "logoUrl": null,
  "parentId": null
}

Responses

200Organization updated.
Content-Type: application/json
{
  "ok": true
}
400Validation failed
Content-Type: application/json
{
  "error": "string"
}
401Authentication required
Content-Type: application/json
{
  "error": "string"
}
403Missing directory.organizations.manage feature
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X PUT "http://108.165.128.56:3000/api/directory/organizations" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"slug\": null,
  \"logoUrl\": null,
  \"parentId\": null
}"
DELETE/directory/organizations
Auth required

Delete organization

Soft deletes an organization identified by id.

Request body (application/json)

{
  "id": "00000000-0000-4000-8000-000000000000"
}

Responses

200Organization deleted.
Content-Type: application/json
{
  "ok": true
}
400Validation failed
Content-Type: application/json
{
  "error": "string"
}
401Authentication required
Content-Type: application/json
{
  "error": "string"
}
403Missing directory.organizations.manage feature
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/directory/organizations" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
GET/directory/tenants
Auth required

List tenants

Returns tenants visible to the current user with optional search and pagination.

Parameters

NameInRequiredSchemaDescription
idqueryNoany—
pagequeryNoany—
pageSizequeryNoany—
searchqueryNoany—
sortFieldqueryNoany—
sortDirqueryNoany—
isActivequeryNoany—

Responses

200Paged list of tenants.
Content-Type: application/json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "name": "string",
      "isActive": true,
      "createdAt": null,
      "updatedAt": null
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
400Invalid query parameters
Content-Type: application/json
{
  "error": "string"
}
401Authentication required
Content-Type: application/json
{
  "error": "string"
}
403Requires super-admin
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/directory/tenants?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/directory/tenants
Auth required

Create tenant

Creates a new tenant and returns its identifier.

Request body (application/json)

{
  "name": "string"
}

Responses

201Tenant created.
Content-Type: application/json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
400Validation failed
Content-Type: application/json
{
  "error": "string"
}
401Authentication required
Content-Type: application/json
{
  "error": "string"
}
403Missing directory.tenants.manage feature
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/directory/tenants" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"name\": \"string\"
}"
PUT/directory/tenants
Auth required

Update tenant

Updates tenant properties such as name or activation state.

Request body (application/json)

{
  "id": "00000000-0000-4000-8000-000000000000"
}

Responses

200Tenant updated.
Content-Type: application/json
{
  "ok": true
}
400Validation failed
Content-Type: application/json
{
  "error": "string"
}
401Authentication required
Content-Type: application/json
{
  "error": "string"
}
403Missing directory.tenants.manage feature
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X PUT "http://108.165.128.56:3000/api/directory/tenants" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
DELETE/directory/tenants
Auth required

Delete tenant

Soft deletes the tenant identified by id.

Request body (application/json)

{
  "id": "00000000-0000-4000-8000-000000000000"
}

Responses

200Tenant removed.
Content-Type: application/json
{
  "ok": true
}
400Validation failed
Content-Type: application/json
{
  "error": "string"
}
401Authentication required
Content-Type: application/json
{
  "error": "string"
}
403Missing directory.tenants.manage feature
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/directory/tenants" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"

Entities

Showing 19 of 19 endpoints
GET/entities/definitions
Auth required

List active custom field definitions

Returns active custom field definitions for the supplied entity ids, respecting tenant scope and tombstones.

Parameters

NameInRequiredSchemaDescription
entityIdqueryNoany—
entityIdsqueryNoany—
fieldsetqueryNoany—

Responses

200Definition list
Content-Type: application/json
{
  "items": [
    {
      "key": "string",
      "kind": "string",
      "label": "string",
      "entityId": "string"
    }
  ]
}
400Missing entity id
Content-Type: application/json
{
  "error": "string"
}
401Missing authentication
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/entities/definitions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/entities/definitions
Auth required

Upsert custom field definition

Creates or updates a custom field definition for the current tenant/org scope.

Request body (application/json)

{
  "entityId": "string",
  "key": "string",
  "kind": "text"
}

Responses

200Definition saved
Content-Type: application/json
{
  "ok": true,
  "item": {
    "id": "00000000-0000-4000-8000-000000000000",
    "key": "string",
    "kind": "string",
    "configJson": {}
  }
}
400Validation failed
Content-Type: application/json
{
  "error": "string"
}
401Missing authentication
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/entities/definitions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"entityId\": \"string\",
  \"key\": \"string\",
  \"kind\": \"text\"
}"
DELETE/entities/definitions
Auth required

Soft delete custom field definition

Marks the specified definition inactive and tombstones it for the current scope.

Request body (application/json)

{
  "entityId": "string",
  "key": "string"
}

Responses

200Definition deleted
Content-Type: application/json
{
  "ok": true,
  "version": null
}
400Missing entity id or key
Content-Type: application/json
{
  "error": "string"
}
401Missing authentication
Content-Type: application/json
{
  "error": "string"
}
404Definition not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/entities/definitions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"entityId\": \"string\",
  \"key\": \"string\"
}"
POST/entities/definitions.batch
Auth required

Save multiple custom field definitions

Creates or updates multiple definitions for a single entity in one transaction.

Request body (application/json)

{
  "entityId": "string",
  "definitions": [
    {
      "key": "string",
      "kind": "text"
    }
  ]
}

Responses

200Definitions saved
Content-Type: application/json
{
  "ok": true,
  "version": null
}
400Validation error
Content-Type: application/json
{
  "error": "string"
}
401Missing authentication
Content-Type: application/json
{
  "error": "string"
}
500Unexpected failure
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/entities/definitions.batch" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"entityId\": \"string\",
  \"definitions\": [
    {
      \"key\": \"string\",
      \"kind\": \"text\"
    }
  ]
}"
GET/entities/definitions.manage
Auth required

Get management snapshot

Returns scoped custom field definitions (including inactive tombstones) for administration interfaces.

Parameters

NameInRequiredSchemaDescription
entityIdqueryYesany—

Responses

200Scoped definitions and deleted keys
Content-Type: application/json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "key": "string",
      "kind": "string",
      "configJson": null,
      "organizationId": null,
      "tenantId": null
    }
  ],
  "deletedKeys": [
    "string"
  ],
  "version": null
}
400Missing entity id
Content-Type: application/json
{
  "error": "string"
}
401Missing authentication or feature
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/entities/definitions.manage?entityId=string" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/entities/definitions.restore
Auth required

Restore definition

Reactivates a previously soft-deleted definition within the current tenant/org scope.

Request body (application/json)

{
  "entityId": "string",
  "key": "string"
}

Responses

200Definition restored
Content-Type: application/json
{
  "ok": true
}
400Missing entity id or key
Content-Type: application/json
{
  "error": "string"
}
401Missing authentication
Content-Type: application/json
{
  "error": "string"
}
404Definition not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/entities/definitions.restore" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"entityId\": \"string\",
  \"key\": \"string\"
}"
GET/entities/encryption
Auth required

Fetch encryption map

Returns the encrypted field map for the current tenant/organization scope.

Parameters

NameInRequiredSchemaDescription
entityIdqueryYesany—

Responses

200Map
Content-Type: application/json
{
  "entityId": "string",
  "fields": [
    {
      "field": "string",
      "hashField": null
    }
  ],
  "updatedAt": null
}

Example

curl -X GET "http://108.165.128.56:3000/api/entities/encryption?entityId=string" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/entities/encryption
Auth required

Upsert encryption map

Creates or updates the encryption map for the current tenant/organization scope. Enforces optimistic locking when the caller sends the expected version header.

Request body (application/json)

{
  "entityId": "string",
  "tenantId": null,
  "organizationId": null,
  "fields": [
    {
      "field": "string",
      "hashField": null
    }
  ]
}

Responses

200Saved
Content-Type: application/json
{
  "ok": true,
  "updatedAt": null
}
409Optimistic-lock conflict (stale write)
Content-Type: application/json
{
  "error": "string",
  "code": "string",
  "currentUpdatedAt": "string",
  "expectedUpdatedAt": "string"
}
422Selected organization is unavailable
Content-Type: application/json
{
  "error": "string",
  "code": "organization_selection_invalid"
}

Example

curl -X POST "http://108.165.128.56:3000/api/entities/encryption" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"entityId\": \"string\",
  \"tenantId\": null,
  \"organizationId\": null,
  \"fields\": [
    {
      \"field\": \"string\",
      \"hashField\": null
    }
  ]
}"
GET/entities/entities
Auth required

List available entities

Returns generated and custom entities scoped to the caller with field counts per entity.

Responses

200List of entities
Content-Type: application/json
{
  "items": [
    {
      "entityId": "string",
      "source": "code",
      "label": "string",
      "count": 1
    }
  ]
}
401Missing authentication
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/entities/entities" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/entities/entities
Auth required

Upsert custom entity

Creates or updates a tenant/org scoped custom entity definition.

Request body (application/json)

{
  "entityId": "string",
  "label": "string",
  "description": null,
  "showInSidebar": false,
  "accessRestricted": false
}

Responses

200Entity saved
Content-Type: application/json
{
  "ok": true,
  "item": {
    "id": "00000000-0000-4000-8000-000000000000",
    "entityId": "string",
    "label": "string"
  }
}
400Validation error
Content-Type: application/json
{
  "error": "string"
}
401Missing authentication
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/entities/entities" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"entityId\": \"string\",
  \"label\": \"string\",
  \"description\": null,
  \"showInSidebar\": false,
  \"accessRestricted\": false
}"
DELETE/entities/entities
Auth required

Soft delete custom entity

Marks the specified custom entity inactive within the current scope.

Request body (application/json)

{
  "entityId": "string"
}

Responses

200Entity deleted
Content-Type: application/json
{
  "ok": true
}
400Missing entity id
Content-Type: application/json
{
  "error": "string"
}
401Missing authentication
Content-Type: application/json
{
  "error": "string"
}
404Entity not found in scope
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/entities/entities" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"entityId\": \"string\"
}"
GET/entities/entity-settings
Auth required

Get custom entity settings

Returns the tenant-scoped default-restricted policy for new custom entities.

Responses

200Current settings
Content-Type: application/json
{
  "newEntitiesRestrictedByDefault": true,
  "updatedAt": null
}
401Missing authentication
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/entities/entity-settings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
PUT/entities/entity-settings
Auth required

Update custom entity settings

Sets the tenant-scoped default-restricted policy for new custom entities.

Request body (application/json)

{
  "newEntitiesRestrictedByDefault": true
}

Responses

200Updated settings
Content-Type: application/json
{
  "ok": true,
  "newEntitiesRestrictedByDefault": true,
  "updatedAt": null
}
400Invalid payload
Content-Type: application/json
{
  "error": "string"
}
401Missing authentication
Content-Type: application/json
{
  "error": "string"
}
409Optimistic lock conflict
Content-Type: application/json
{
  "code": "string",
  "error": "string"
}

Example

curl -X PUT "http://108.165.128.56:3000/api/entities/entity-settings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"newEntitiesRestrictedByDefault\": true
}"
GET/entities/records
Auth required

List records

Returns paginated records for the supplied entity. Supports custom field filters, exports, and soft-delete toggles.

Parameters

NameInRequiredSchemaDescription
entityIdqueryYesany—
pagequeryNoany—
pageSizequeryNoany—
sortFieldqueryNoany—
sortDirqueryNoany—
searchqueryNoany—
searchFieldsqueryNoany—
withDeletedqueryNoany—
formatqueryNoany—
exportScopequeryNoany—
export_scopequeryNoany—
allqueryNoany—
fullqueryNoany—

Responses

200Paginated records
Content-Type: application/json
{
  "items": [
    {}
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
400Missing entity id
Content-Type: application/json
{
  "error": "string"
}
401Missing authentication
Content-Type: application/json
{
  "error": "string"
}
500Unexpected failure
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/entities/records?entityId=string" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/entities/records
Auth required

Create record

Creates a record for the given entity. When `recordId` is omitted or not a UUID the data engine will generate one automatically.

Request body (application/json)

{
  "entityId": "string",
  "values": {}
}

Responses

200Record created
Content-Type: application/json
{
  "ok": true
}
400Validation failure
Content-Type: application/json
{
  "error": "string"
}
401Missing authentication
Content-Type: application/json
{
  "error": "string"
}
500Unexpected failure
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/entities/records" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"entityId\": \"string\",
  \"values\": {}
}"
PUT/entities/records
Auth required

Update record

Updates an existing record. If the provided recordId is not a UUID the record will be created instead to support optimistic flows.

Request body (application/json)

{
  "entityId": "string",
  "recordId": "string",
  "values": {}
}

Responses

200Record updated
Content-Type: application/json
{
  "ok": true
}
400Validation failure
Content-Type: application/json
{
  "error": "string"
}
401Missing authentication
Content-Type: application/json
{
  "error": "string"
}
500Unexpected failure
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X PUT "http://108.165.128.56:3000/api/entities/records" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"entityId\": \"string\",
  \"recordId\": \"string\",
  \"values\": {}
}"
DELETE/entities/records
Auth required

Delete record

Soft deletes the specified record within the current tenant/org scope.

Request body (application/json)

{
  "entityId": "string",
  "recordId": "string"
}

Responses

200Record deleted
Content-Type: application/json
{
  "ok": true
}
400Missing entity id or record id
Content-Type: application/json
{
  "error": "string"
}
401Missing authentication
Content-Type: application/json
{
  "error": "string"
}
404Record not found
Content-Type: application/json
{
  "error": "string"
}
500Unexpected failure
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/entities/records" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"entityId\": \"string\",
  \"recordId\": \"string\"
}"
GET/entities/relations/options
Auth required

List relation options

Returns up to 200 option entries for populating relation dropdowns, automatically resolving label fields when omitted. An entityId that matches neither an active custom entity nor a registered ORM entity yields an empty option list.

Parameters

NameInRequiredSchemaDescription
entityIdqueryYesany—
labelFieldqueryNoany—
qqueryNoany—
idsqueryNoany—
routeContextFieldsqueryNoany—

Responses

200Option list
Content-Type: application/json
{
  "items": [
    {
      "value": "string",
      "label": "string"
    }
  ]
}
401Missing authentication
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/entities/relations/options?entityId=string" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/entities/sidebar-entities
Auth required

Get sidebar entities

Returns custom entities flagged with `showInSidebar` for the current tenant/org scope.

Responses

200Sidebar entities for navigation
Content-Type: application/json
{
  "items": [
    {
      "entityId": "string",
      "label": "string",
      "href": "string"
    }
  ]
}
401Missing authentication
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/entities/sidebar-entities" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"

PaymentGateways

Showing 11 of 11 endpoints
POST/payment_gateways/cancel
Auth required

Cancel payment

Responses

200Payment cancelled
Content-Type: application/json
"string"
409Invalid payment status transition
Content-Type: application/json
"string"
422Invalid payload
Content-Type: application/json
"string"
502Gateway provider error
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/payment_gateways/cancel" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/payment_gateways/capture
Auth required

Capture payment

Responses

200Payment captured
Content-Type: application/json
"string"
409Invalid payment status transition, cumulative capture ceiling exceeded, or conflicting capture operation
Content-Type: application/json
"string"
422Invalid payload
Content-Type: application/json
"string"
502Gateway provider error
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/payment_gateways/capture" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/payment_gateways/providers
Auth required

List payment gateway descriptors

Responses

200List of safe payment gateway descriptors
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/payment_gateways/providers" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/payment_gateways/providers/{providerKey}
Auth required

Get payment gateway descriptor

Parameters

NameInRequiredSchemaDescription
providerKeypathYesany—

Responses

200Provider descriptor
Content-Type: application/json
"string"
404Provider descriptor not found
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/payment_gateways/providers/:providerKey" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/payment_gateways/refund
Auth required

Refund payment

Responses

200Payment refunded
Content-Type: application/json
"string"
409Invalid payment status transition
Content-Type: application/json
"string"
422Invalid payload
Content-Type: application/json
"string"
502Gateway provider error
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/payment_gateways/refund" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/payment_gateways/sessions
Auth required

Create payment session

Responses

201Payment session created
Content-Type: application/json
"string"
409Amount or currency does not match the referenced order
Content-Type: application/json
"string"
422Invalid payload or unknown provider
Content-Type: application/json
"string"
502Gateway provider error
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/payment_gateways/sessions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/payment_gateways/status
Auth required

Get stored transaction status

Responses

200Stored transaction status
Content-Type: application/json
"string"
400Missing or malformed transactionId
Content-Type: application/json
"string"
404Transaction not found
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/payment_gateways/status" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/payment_gateways/status
Auth required

Refresh transaction status from the provider

Responses

200Refreshed transaction status
Content-Type: application/json
"string"
401Unauthorized
Content-Type: application/json
"string"
404Transaction not found
Content-Type: application/json
"string"
422Missing or malformed payload
Content-Type: application/json
"string"
502Gateway provider error
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/payment_gateways/status" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/payment_gateways/transactions
Auth required

List payment transactions

Responses

200Payment transaction list
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/payment_gateways/transactions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/payment_gateways/transactions/{id}
Auth required

Get payment transaction details

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Payment transaction details
Content-Type: application/json
"string"
404Transaction not found
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/payment_gateways/transactions/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/payment_gateways/webhook/{provider}

Process inbound webhook from payment provider

Parameters

NameInRequiredSchemaDescription
providerpathYesany—

Responses

202Webhook accepted for async processing
Content-Type: application/json
"string"
401Signature verification failed
Content-Type: application/json
"string"
404Unknown provider
Content-Type: application/json
"string"
413Webhook payload too large
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/payment_gateways/webhook/:provider" \
  -H "Accept: application/json"

PhoneCalls

Showing 1 of 1 endpoints
GET/phone_calls/calls
Auth required

List phonecalls

Returns a paginated collection of phonecalls scoped to the authenticated organization.

Parameters

NameInRequiredSchemaDescription
pagequeryNoany—
pageSizequeryNoany—
qqueryNoany—
providerKeyqueryNoany—
statusqueryNoany—
directionqueryNoany—
startedFromqueryNoany—
startedToqueryNoany—
sortFieldqueryNoany—
sortDirqueryNoany—
idqueryNoany—
idsqueryNoanyComma-separated list of record UUIDs to filter by (max 200).

Responses

200Paginated phonecalls
Content-Type: application/json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "organization_id": null,
      "tenant_id": null,
      "provider_key": null,
      "integration_id": null,
      "external_call_id": null,
      "external_conversation_id": null,
      "direction": null,
      "status": null,
      "started_at": null,
      "answered_at": null,
      "ended_at": null,
      "duration_seconds": null,
      "recording_url": null,
      "ingest_status": null,
      "last_ingested_at": null,
      "created_at": null,
      "updated_at": null
    }
  ],
  "total": 1,
  "totalPages": 1
}

Example

curl -X GET "http://108.165.128.56:3000/api/phone_calls/calls?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"

Query Index

Showing 3 of 3 endpoints
POST/query_index/purge
Auth required

Purge query index records

Queues a purge job to remove indexed records for an entity type within the active scope.

Request body (application/json)

{
  "entityType": "string"
}

Responses

200Purge job accepted.
Content-Type: application/json
{
  "ok": true
}
400Missing entity type
Content-Type: application/json
{
  "error": "string"
}
401Authentication required
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/query_index/purge" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"entityType\": \"string\"
}"
POST/query_index/reindex
Auth required

Trigger query index rebuild

Queues a reindex job for the specified entity type within the current tenant scope.

Request body (application/json)

{
  "entityType": "string"
}

Responses

200Reindex job accepted.
Content-Type: application/json
{
  "ok": true
}
400Missing entity type
Content-Type: application/json
{
  "error": "string"
}
401Authentication required
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/query_index/reindex" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"entityType\": \"string\"
}"
GET/query_index/status
Auth required

Inspect query index coverage

Returns entity counts comparing base tables with the query index along with the latest job status.

Responses

200Current query index status.
Content-Type: application/json
{
  "items": [
    {
      "entityId": "string",
      "label": "string",
      "baseCount": null,
      "indexCount": null,
      "vectorCount": null,
      "fulltextCount": null,
      "ok": true,
      "job": {
        "status": "idle",
        "startedAt": null,
        "finishedAt": null,
        "heartbeatAt": null,
        "processedCount": null,
        "totalCount": null,
        "scope": null
      },
      "refreshedAt": null
    }
  ],
  "errors": [
    {
      "id": "string",
      "source": "string",
      "handler": "string",
      "entityType": null,
      "recordId": null,
      "tenantId": null,
      "organizationId": null,
      "message": "string",
      "stack": null,
      "payload": null,
      "occurredAt": "string"
    }
  ],
  "logs": [
    {
      "id": "string",
      "source": "string",
      "handler": "string",
      "level": "info",
      "entityType": null,
      "recordId": null,
      "tenantId": null,
      "organizationId": null,
      "message": "string",
      "details": null,
      "occurredAt": "string"
    }
  ]
}
400Tenant or organization context required
Content-Type: application/json
{
  "error": "string"
}
401Authentication required
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/query_index/status" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"

Rich Methods Automation

Showing 8 of 8 endpoints
GET/richmethods_automation/recipe-instances
Auth required

List automation recipes

Returns a paginated collection of automation recipes in the current tenant and organization scope.

Parameters

NameInRequiredSchemaDescription
idqueryNoany—
pagequeryNoany—
pageSizequeryNoany—
searchqueryNoany—
statusqueryNoany—
templateKeyqueryNoany—
sortFieldqueryNoany—
sortDirqueryNoany—
idsqueryNoanyComma-separated list of record UUIDs to filter by (max 200).

Responses

200Paginated automation recipes
Content-Type: application/json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "template_key": "string",
      "display_name": "string",
      "status": "draft",
      "assistant_id": null,
      "supervisor_user_id": null,
      "trigger_event": null,
      "assistant_invocable": true,
      "approval_mode": "none",
      "config_version": 1,
      "created_at": "string",
      "updated_at": "string"
    }
  ],
  "total": 1,
  "totalPages": 1
}

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_automation/recipe-instances?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/richmethods_automation/recipe-instances
Auth required

Create automation recipe

Creates a tenant recipe instance. Activation requires a complete, authorized configuration.

Request body (application/json)

{
  "templateKey": "string",
  "displayName": "string",
  "status": "draft",
  "assistantId": null,
  "supervisorUserId": null,
  "triggerEvent": null,
  "assistantInvocable": false,
  "parameters": {},
  "workflowId": null,
  "integrationBindings": [],
  "usageTags": {}
}

Responses

201Automation recipe created
Content-Type: application/json
{
  "id": "00000000-0000-4000-8000-000000000000"
}

Example

curl -X POST "http://108.165.128.56:3000/api/richmethods_automation/recipe-instances" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"templateKey\": \"string\",
  \"displayName\": \"string\",
  \"status\": \"draft\",
  \"assistantId\": null,
  \"supervisorUserId\": null,
  \"triggerEvent\": null,
  \"assistantInvocable\": false,
  \"parameters\": {},
  \"workflowId\": null,
  \"integrationBindings\": [],
  \"usageTags\": {}
}"
PUT/richmethods_automation/recipe-instances
Auth required

Update automation recipe

Updates a recipe instance using its optimistic-lock version.

Request body (application/json)

{
  "id": "00000000-0000-4000-8000-000000000000",
  "updatedAt": "string",
  "status": "draft",
  "assistantId": null,
  "supervisorUserId": null,
  "triggerEvent": null,
  "assistantInvocable": false,
  "parameters": {},
  "workflowId": null,
  "integrationBindings": [],
  "usageTags": {}
}

Responses

200Automation recipe updated
Content-Type: application/json
{
  "ok": true
}

Example

curl -X PUT "http://108.165.128.56:3000/api/richmethods_automation/recipe-instances" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"updatedAt\": \"string\",
  \"status\": \"draft\",
  \"assistantId\": null,
  \"supervisorUserId\": null,
  \"triggerEvent\": null,
  \"assistantInvocable\": false,
  \"parameters\": {},
  \"workflowId\": null,
  \"integrationBindings\": [],
  \"usageTags\": {}
}"
DELETE/richmethods_automation/recipe-instances
Auth required

Delete automation recipe

Soft-deletes a recipe instance.

Request body (application/json)

{
  "id": "00000000-0000-4000-8000-000000000000",
  "updatedAt": "string"
}

Responses

200Automation recipe deleted
Content-Type: application/json
{
  "ok": true
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/richmethods_automation/recipe-instances" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"updatedAt\": \"string\"
}"
GET/richmethods_automation/recipe-readiness
Auth required

Evaluate recipe readiness

Returns the effective status and configuration issues of each recipe in scope.

Responses

200Readiness per recipe instance.
Content-Type: application/json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "effectiveStatus": "string",
      "issues": [
        {
          "code": "string"
        }
      ]
    }
  ]
}
403Forbidden.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_automation/recipe-readiness" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/richmethods_automation/recipe-runs
Auth required

List recipe runs

Lists runs with customer-facing state derived from native approval state.

Parameters

NameInRequiredSchemaDescription
pagequeryNoany—
pageSizequeryNoany—
recipeInstanceIdqueryNoany—

Responses

200Recipe runs.
Content-Type: application/json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "recipeInstanceId": "00000000-0000-4000-8000-000000000000",
      "templateKey": "string",
      "triggerType": "string",
      "subjectId": null,
      "status": "string",
      "state": "string",
      "pendingActionId": null,
      "workflowInstanceId": null,
      "assistantId": null,
      "attribution": {},
      "errorCode": null,
      "createdAt": "string"
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1
}
403Forbidden.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_automation/recipe-runs?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/richmethods_automation/recipe-runs
Auth required

Invoke a recipe

Invokes an active recipe instance. Protected actions become native pending approvals.

Request body (application/json)

{
  "recipeInstanceId": "00000000-0000-4000-8000-000000000000"
}

Responses

201Run recorded.
Content-Type: application/json
{
  "runId": "00000000-0000-4000-8000-000000000000",
  "status": "string",
  "pendingActionId": null,
  "duplicate": true
}
400Invalid request.
Content-Type: application/json
{
  "error": "string"
}
403Invocation denied.
Content-Type: application/json
{
  "error": "string"
}
404Recipe not found in scope.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/richmethods_automation/recipe-runs" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"recipeInstanceId\": \"00000000-0000-4000-8000-000000000000\"
}"
GET/richmethods_automation/recipe-templates
Auth required

List recipe templates

Returns the reusable Rich Methods automation recipe templates.

Responses

200Recipe templates.
Content-Type: application/json
{
  "templates": [
    {
      "key": "string",
      "name": "string",
      "description": "string",
      "category": "string",
      "triggerEvents": [
        "string"
      ],
      "manualTrigger": true,
      "assistantTrigger": true,
      "action": "string",
      "requiredCapabilities": [
        "string"
      ],
      "requiredFeatures": [
        "string"
      ],
      "defaultApprovalMode": "string",
      "approvalLocked": true,
      "assistantRequired": true,
      "supervisorRequired": true,
      "defaultParameters": {},
      "integrationRequirements": [
        {
          "type": "string",
          "required": true,
          "availability": "string"
        }
      ],
      "suggestedJobTemplateIds": [
        "string"
      ]
    }
  ]
}
401Authentication required.
Content-Type: application/json
{
  "error": "string"
}
403The user cannot view recipes.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_automation/recipe-templates" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"

Rich Methods Commerce

Showing 20 of 71 endpoints
GET/richmethods_commerce/ai-rate-cards
Auth required

List versioned AI rates

Returns immutable rate-card versions in the authenticated tenant and organization scope.

Responses

200Success.
Content-Type: application/json
{}
401Unauthorized.
Content-Type: application/json
{
  "error": "string"
}
403Forbidden.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_commerce/ai-rate-cards" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/richmethods_commerce/ai-rate-cards
Auth required

Create an AI rate-card version

Creates the next immutable effective-dated provider/model rate version. Only users with rate-management authority may create versions.

Request body (application/json)

{
  "providerId": "string",
  "modelId": "string",
  "currency": "string",
  "effectiveFrom": "string",
  "meters": {
    "key": {
      "unit": "string",
      "minorPerUnitNumerator": "string",
      "minorPerUnitDenominator": "string"
    }
  }
}

Responses

200Success.
Content-Type: application/json
{}
400Invalid or backdated rate card.
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized.
Content-Type: application/json
{
  "error": "string"
}
403Rate management is not authorized.
Content-Type: application/json
{
  "error": "string"
}
409The rate-card version conflicts with a concurrent or earlier effective version.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/richmethods_commerce/ai-rate-cards" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"providerId\": \"string\",
  \"modelId\": \"string\",
  \"currency\": \"string\",
  \"effectiveFrom\": \"string\",
  \"meters\": {
    \"key\": {
      \"unit\": \"string\",
      \"minorPerUnitNumerator\": \"string\",
      \"minorPerUnitDenominator\": \"string\"
    }
  }
}"
GET/richmethods_commerce/ai-usage
Auth required

Read AI budget status and recent actual costs

Returns scoped customer-business budgets, actual accumulated costs, outstanding reservations, remaining budget, and recent reconciled usage.

Responses

200Success.
Content-Type: application/json
{}
401Unauthorized.
Content-Type: application/json
{
  "error": "string"
}
403Forbidden.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_commerce/ai-usage" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/richmethods_commerce/ai-usage
Auth required

Reserve AI budget before provider work

Authorizes a paid operation only when a scoped rate card and policy exist and the maximum expected charge fits within the hard maximum. Work Level and mutation approval remain independent.

Request body (application/json)

{
  "businessKey": "string",
  "correlationId": "00000000-0000-4000-8000-000000000000",
  "assistantId": null,
  "capability": "string",
  "providerId": "string",
  "modelId": "string",
  "maximumUsage": {
    "inputTokens": 0,
    "cachedInputTokens": 0,
    "outputTokens": 0,
    "reasoningTokens": 0,
    "providerBillableUnits": {},
    "toolApiChargesMinor": {}
  }
}

Responses

200Success.
Content-Type: application/json
{}
400Invalid request.
Content-Type: application/json
{
  "error": "string"
}
402Paid AI budget is missing or exhausted.
Content-Type: application/json
{
  "error": "string"
}
403Paid capability is not allowed.
Content-Type: application/json
{
  "error": "string"
}
409Correlation or currency conflict.
Content-Type: application/json
{
  "error": "string"
}
503No effective rate card exists.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/richmethods_commerce/ai-usage" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"businessKey\": \"string\",
  \"correlationId\": \"00000000-0000-4000-8000-000000000000\",
  \"assistantId\": null,
  \"capability\": \"string\",
  \"providerId\": \"string\",
  \"modelId\": \"string\",
  \"maximumUsage\": {
    \"inputTokens\": 0,
    \"cachedInputTokens\": 0,
    \"outputTokens\": 0,
    \"reasoningTokens\": 0,
    \"providerBillableUnits\": {},
    \"toolApiChargesMinor\": {}
  }
}"
PATCH/richmethods_commerce/ai-usage
Auth required

Reconcile actual provider usage

Settles an existing reservation with normalized provider usage and the immutable rate-card version recorded at authorization.

Request body (application/json)

{
  "correlationId": "00000000-0000-4000-8000-000000000000",
  "usage": {
    "inputTokens": 0,
    "cachedInputTokens": 0,
    "outputTokens": 0,
    "reasoningTokens": 0,
    "providerBillableUnits": {},
    "toolApiChargesMinor": {}
  }
}

Responses

200Success.
Content-Type: application/json
{}
400Invalid usage data.
Content-Type: application/json
{
  "error": "string"
}
403Reconciliation is not authorized.
Content-Type: application/json
{
  "error": "string"
}
404Reservation not found.
Content-Type: application/json
{
  "error": "string"
}
409Reservation cannot be reconciled.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X PATCH "http://108.165.128.56:3000/api/richmethods_commerce/ai-usage" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"correlationId\": \"00000000-0000-4000-8000-000000000000\",
  \"usage\": {
    \"inputTokens\": 0,
    \"cachedInputTokens\": 0,
    \"outputTokens\": 0,
    \"reasoningTokens\": 0,
    \"providerBillableUnits\": {},
    \"toolApiChargesMinor\": {}
  }
}"
GET/richmethods_commerce/beta-health
Auth required

Read scoped commercial and operating source counts

Returns exact active offer/subscription, provisioning, owner activation, connected-provider, reconciled AI cost-event and first-outcome record counts for the authenticated tenant and organization. Acquisition, campaign performance, automation, refunds, retention, expansion and support costs are explicitly unavailable because those sources are not currently captured; no revenue, ROI, CAC, LTV or margin is inferred.

Responses

200Source-backed counts and an explicit list of unavailable analytics sources.
Content-Type: application/json
{
  "offers": {
    "active": {
      "availability": "measured",
      "value": null
    }
  },
  "subscriptions": {
    "activeRecords": {
      "availability": "measured",
      "value": null
    }
  },
  "provisioning": {
    "runs": {
      "availability": "measured",
      "value": null
    },
    "ownerActivations": {
      "availability": "measured",
      "value": null
    }
  },
  "integrations": {
    "connectedRecords": {
      "availability": "measured",
      "value": null
    }
  },
  "ai": {
    "reconciledCostEvents": {
      "availability": "measured",
      "value": null
    }
  },
  "outcomes": {
    "firstBusinessOutcomes": {
      "availability": "measured",
      "value": null
    }
  },
  "unavailableSources": [
    "acquisition_visits"
  ]
}
401Staff authentication is required.
Content-Type: application/json
"string"
403The caller cannot view Beta Health.
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_commerce/beta-health" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/richmethods_commerce/blueprints
Auth required

List blueprints and instances

Scope-filtered.

Responses

200Success.
Content-Type: application/json
{}
401Unauthorized.
Content-Type: application/json
{
  "error": "string"
}
403Forbidden.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_commerce/blueprints" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/richmethods_commerce/business-blueprints
Auth required

List scoped business packages

Returns scoped blueprint versions, definitions for authorized catalog managers, release permissions, and optional server-side search and pagination.

Responses

200Success.
Content-Type: application/json
{}
401Unauthorized.
Content-Type: application/json
{
  "error": "string"
}
403Forbidden.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_commerce/business-blueprints" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/richmethods_commerce/business-blueprints
Auth required

Create a complete immutable business package draft

Creates a draft package and its first separately versioned business plan in one database transaction. It cannot be published or represented as sale-ready.

Request body (application/json)

{
  "key": "string",
  "version": 1,
  "name": "string",
  "businessType": "string",
  "description": "string",
  "status": "draft",
  "sections": {},
  "businessPlan": {
    "version": 1,
    "sections": {
      "executiveSummary": "string",
      "companyDescription": "string",
      "marketAndCustomer": "string",
      "servicesAndProducts": "string",
      "revenueModel": "string",
      "competitivePosition": "string",
      "marketingPlan": "string",
      "salesPlan": "string",
      "operationsPlan": "string",
      "technologyAndAutomation": "string",
      "staffingAndAiAssistance": "string",
      "startupRequirements": "string",
      "licensingAndRegulatoryConsiderations": "string",
      "financialAssumptions": "string",
      "launchPlan": "string",
      "growthPlan": "string",
      "risksAndDependencies": "string"
    },
    "disclaimer": "Financial assumptions are estimates, not guaranteed income."
  },
  "planVersion": 1,
  "setupMode": "self_setup",
  "jurisdiction": "string"
}

Responses

200Success.
Content-Type: application/json
{}
401Unauthorized.
Content-Type: application/json
{
  "error": "string"
}
403Forbidden.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/richmethods_commerce/business-blueprints" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"key\": \"string\",
  \"version\": 1,
  \"name\": \"string\",
  \"businessType\": \"string\",
  \"description\": \"string\",
  \"status\": \"draft\",
  \"sections\": {},
  \"businessPlan\": {
    \"version\": 1,
    \"sections\": {
      \"executiveSummary\": \"string\",
      \"companyDescription\": \"string\",
      \"marketAndCustomer\": \"string\",
      \"servicesAndProducts\": \"string\",
      \"revenueModel\": \"string\",
      \"competitivePosition\": \"string\",
      \"marketingPlan\": \"string\",
      \"salesPlan\": \"string\",
      \"operationsPlan\": \"string\",
      \"technologyAndAutomation\": \"string\",
      \"staffingAndAiAssistance\": \"string\",
      \"startupRequirements\": \"string\",
      \"licensingAndRegulatoryConsiderations\": \"string\",
      \"financialAssumptions\": \"string\",
      \"launchPlan\": \"string\",
      \"growthPlan\": \"string\",
      \"risksAndDependencies\": \"string\"
    },
    \"disclaimer\": \"Financial assumptions are estimates, not guaranteed income.\"
  },
  \"planVersion\": 1,
  \"setupMode\": \"self_setup\",
  \"jurisdiction\": \"string\"
}"
PATCH/richmethods_commerce/business-blueprints
Auth required

Test and release a business package version

Requires a complete business plan and exact plan association for test, approval and publication. Lifecycle actions preserve the same immutable package version.

Request body (application/json)

{
  "key": "string",
  "version": 1,
  "updatedAt": "string"
}

Responses

200Success.
Content-Type: application/json
{}
401Unauthorized.
Content-Type: application/json
{
  "error": "string"
}
403Forbidden.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X PATCH "http://108.165.128.56:3000/api/richmethods_commerce/business-blueprints" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"key\": \"string\",
  \"version\": 1,
  \"updatedAt\": \"string\"
}"
GET/richmethods_commerce/business-outcomes
Auth required

Read source-backed first business outcomes for the active organization

Returns only persisted first-outcome audit events in the authenticated tenant and organization. An empty outcome set is unavailable, not a measured zero. The timestamp basis distinguishes a source occurrence timestamp from when the subscriber observed an event without one.

Responses

200At most the 100 latest attributable outcomes and their measured/unavailable state.
Content-Type: application/json
{
  "availability": "measured",
  "total": null,
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "productKey": "string",
      "productVersion": 1,
      "blueprintKey": "string",
      "blueprintVersion": 1,
      "milestoneKey": "string",
      "milestoneLabel": "string",
      "sourceEventId": "customers.deal.won",
      "measurementTimestamp": "source_occurred_at",
      "measuredAt": "string",
      "elapsedMilliseconds": 1,
      "recordedAt": "string"
    }
  ]
}
401Staff authentication is required.
Content-Type: application/json
"string"
403The caller cannot view Beta Health outcomes.
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_commerce/business-outcomes" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/richmethods_commerce/business-owner
Auth required

Read the current business owner and active customer users

Returns the designation for the authenticated staff organization and active customer users in that same tenant and organization. Requires customer_accounts.view.

Responses

200Current designation and active customer user options.
Content-Type: application/json
{
  "item": null,
  "currentUser": null,
  "users": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "displayName": "string",
      "isActive": true
    }
  ]
}
401Unauthorized.
Content-Type: application/json
{
  "error": "string"
}
403Forbidden.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_commerce/business-owner" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
PUT/richmethods_commerce/business-owner
Auth required

Assign or transfer the business owner

Requires explicit out-of-band evidence review. The authenticated staff user is recorded as verifier; tenant and organization scope are never accepted from the body.

Request body (application/json)

{
  "customerUserId": "00000000-0000-4000-8000-000000000000",
  "reviewedOutOfBand": true,
  "updatedAt": null
}

Responses

200Success.
Content-Type: application/json
{}
400Invalid owner designation request.
Content-Type: application/json
"string"
404Customer user is unavailable in this organization.
Content-Type: application/json
"string"
409Owner designation changed; reload before transferring.
Content-Type: application/json
"string"

Example

curl -X PUT "http://108.165.128.56:3000/api/richmethods_commerce/business-owner" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"customerUserId\": \"00000000-0000-4000-8000-000000000000\",
  \"reviewedOutOfBand\": true,
  \"updatedAt\": null
}"
GET/richmethods_commerce/business-plans
Auth required

List scoped versioned business plans

Returns business plan versions associated with Ready Business blueprint versions.

Responses

200Success.
Content-Type: application/json
{}
401Unauthorized.
Content-Type: application/json
{
  "error": "string"
}
403Forbidden.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_commerce/business-plans" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/richmethods_commerce/business-plans
Auth required

Create a business plan version

Creates an immutable, scoped plan version with a non-guaranteed financial assumptions disclaimer.

Request body (application/json)

{
  "blueprintKey": "string",
  "blueprintVersion": 1,
  "planVersion": 1,
  "sections": {
    "executiveSummary": "string",
    "companyDescription": "string",
    "marketAndCustomer": "string",
    "servicesAndProducts": "string",
    "revenueModel": "string",
    "competitivePosition": "string",
    "marketingPlan": "string",
    "salesPlan": "string",
    "operationsPlan": "string",
    "technologyAndAutomation": "string",
    "staffingAndAiAssistance": "string",
    "startupRequirements": "string",
    "licensingAndRegulatoryConsiderations": "string",
    "financialAssumptions": "string",
    "launchPlan": "string",
    "growthPlan": "string",
    "risksAndDependencies": "string"
  }
}

Responses

200Success.
Content-Type: application/json
{}
401Unauthorized.
Content-Type: application/json
{
  "error": "string"
}
403Forbidden.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/richmethods_commerce/business-plans" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"blueprintKey\": \"string\",
  \"blueprintVersion\": 1,
  \"planVersion\": 1,
  \"sections\": {
    \"executiveSummary\": \"string\",
    \"companyDescription\": \"string\",
    \"marketAndCustomer\": \"string\",
    \"servicesAndProducts\": \"string\",
    \"revenueModel\": \"string\",
    \"competitivePosition\": \"string\",
    \"marketingPlan\": \"string\",
    \"salesPlan\": \"string\",
    \"operationsPlan\": \"string\",
    \"technologyAndAutomation\": \"string\",
    \"staffingAndAiAssistance\": \"string\",
    \"startupRequirements\": \"string\",
    \"licensingAndRegulatoryConsiderations\": \"string\",
    \"financialAssumptions\": \"string\",
    \"launchPlan\": \"string\",
    \"growthPlan\": \"string\",
    \"risksAndDependencies\": \"string\"
  }
}"
POST/richmethods_commerce/checkout
Auth required

Provision a TEST/DEMO subscription without payment

This legacy route accepts only TEST/DEMO price-book data and processes no payment; it must not be used for commercial checkout. A matching unexpired reservation may be converted in the same transaction. Commercial checkout remains blocked until the owner-authorized payment path is integrated.

Request body (application/json)

{
  "productKey": "string",
  "interval": "one_time",
  "quantity": 1,
  "idempotencyKey": "string"
}

Responses

200Success.
Content-Type: application/json
{}
401Unauthorized.
Content-Type: application/json
{
  "error": "string"
}
403Forbidden.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/richmethods_commerce/checkout" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"productKey\": \"string\",
  \"interval\": \"one_time\",
  \"quantity\": 1,
  \"idempotencyKey\": \"string\"
}"
GET/richmethods_commerce/entitlements
Auth required

List entitlements

An entitlement is necessary but never sufficient for access; permissions, assignment, approval and spending policy still apply.

Responses

200Success.
Content-Type: application/json
{}
401Unauthorized.
Content-Type: application/json
{
  "error": "string"
}
403Forbidden.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_commerce/entitlements" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/richmethods_commerce/marketing-assessments
Auth required

Read business assessment

Internal authenticated staff; trusted tenant and concrete organization. No customer access or external retrieval.

Responses

200Scoped assessment or null.
Content-Type: application/json
{
  "item": null
}
400Invalid input or query.
Content-Type: application/json
"string"
404Assessment unavailable in the authenticated scope.
Content-Type: application/json
"string"
409Version conflict or assessment still has evidence.
Content-Type: application/json
"string"

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_commerce/marketing-assessments" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/richmethods_commerce/marketing-assessments
Auth required

Create or revise business assessment

Atomic command with mandatory version on edits; no payload scope.

Request body (application/json)

{
  "updatedAt": null,
  "profile": {
    "industry": "",
    "geography": "",
    "businessModel": "unknown",
    "stage": "unknown",
    "offer": "",
    "audience": "",
    "channels": [],
    "capacity": "unknown",
    "constraints": "",
    "evidenceSources": {}
  }
}

Responses

200Saved assessment and current version.
Content-Type: application/json
{
  "item": {
    "id": "00000000-0000-4000-8000-000000000000",
    "profile": {
      "industry": "",
      "geography": "",
      "businessModel": "unknown",
      "stage": "unknown",
      "offer": "",
      "audience": "",
      "channels": [],
      "capacity": "unknown",
      "constraints": "",
      "evidenceSources": {}
    },
    "revision": 1,
    "updatedAt": "string"
  }
}
400Invalid input or query.
Content-Type: application/json
"string"
404Assessment unavailable in the authenticated scope.
Content-Type: application/json
"string"
409Version conflict or assessment still has evidence.
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/richmethods_commerce/marketing-assessments" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"updatedAt\": null,
  \"profile\": {
    \"industry\": \"\",
    \"geography\": \"\",
    \"businessModel\": \"unknown\",
    \"stage\": \"unknown\",
    \"offer\": \"\",
    \"audience\": \"\",
    \"channels\": [],
    \"capacity\": \"unknown\",
    \"constraints\": \"\",
    \"evidenceSources\": {}
  }
}"
DELETE/richmethods_commerce/marketing-assessments
Auth required

Delete empty assessment

Rejects deletion while evidence remains; history snapshots are retained.

Request body (application/json)

{
  "id": "00000000-0000-4000-8000-000000000000",
  "updatedAt": "string"
}

Responses

200Deleted assessment ID.
Content-Type: application/json
{
  "item": {
    "id": "00000000-0000-4000-8000-000000000000"
  }
}
400Invalid input or query.
Content-Type: application/json
"string"
404Assessment unavailable in the authenticated scope.
Content-Type: application/json
"string"
409Version conflict or assessment still has evidence.
Content-Type: application/json
"string"

Example

curl -X DELETE "http://108.165.128.56:3000/api/richmethods_commerce/marketing-assessments" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"updatedAt\": \"string\"
}"

Rich Methods Owner Operations

Showing 20 of 20 endpoints
GET/richmethods_owner_ops/beta-feedback
Auth required

List feedback from active beta testers

Returns only reports in tester tenant and organization scopes actively registered to the authenticated owner.

Responses

200Filtered feedback page.
Content-Type: application/json
{}
401Authentication required.
Content-Type: application/json
{
  "error": "string"
}
403Owner access required.
Content-Type: application/json
{
  "error": "string"
}
409The record changed; reload and retry.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_owner_ops/beta-feedback" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/richmethods_owner_ops/beta-feedback/{id}
Auth required

Read beta feedback details

Returns the selected report only while its tester remains actively registered under the authenticated owner.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Feedback detail.
Content-Type: application/json
{}
401Authentication required.
Content-Type: application/json
{
  "error": "string"
}
403Owner access required.
Content-Type: application/json
{
  "error": "string"
}
409The record changed; reload and retry.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_owner_ops/beta-feedback/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/richmethods_owner_ops/beta-feedback/{id}/action
Auth required

Triage or reply to beta feedback

Updates status or priority, or adds a private reply. The command rechecks owner permission and locks the active tester registration in the same transaction.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Request body (application/json)

{
  "action": "status",
  "status": "open",
  "updatedAt": "string"
}

Responses

200Updated feedback state.
Content-Type: application/json
{}
400The action payload is invalid.
Content-Type: application/json
"string"
403Owner management access or active tester registration is missing.
Content-Type: application/json
"string"
404The feedback record is unavailable.
Content-Type: application/json
"string"
409The record changed, reply key conflicts, or transition is invalid.
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/richmethods_owner_ops/beta-feedback/:id/action" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"action\": \"status\",
  \"status\": \"open\",
  \"updatedAt\": \"string\"
}"
GET/richmethods_owner_ops/beta-testers
Auth required

List owner-scoped beta testers

Lists only the authenticated owner organization registry rows. The encrypted tester email is decrypted for this authorized view; search and sorting by email are not supported.

Parameters

NameInRequiredSchemaDescription
pagequeryNoany—
pageSizequeryNoany—
statusqueryNoany—
testerTypequeryNoany—

Responses

200The paged owner-scoped tester registry.
Content-Type: application/json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "email": "user@example.com",
      "testerType": "business",
      "status": "string",
      "workspaceStatus": "ready",
      "workspaceLabel": "string",
      "createdAt": null,
      "updatedAt": null
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
400The list query is invalid.
Content-Type: application/json
{
  "error": "string"
}
403Owner feature access is required.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_owner_ops/beta-testers?page=1&pageSize=25" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/richmethods_owner_ops/beta-testers
Auth required

Create or safely resume a tester workspace

Creates the owner-scoped tester registry and resumes isolated tenant/organization provisioning. This action does not invite the tester or grant product permissions.

Request body (application/json)

{
  "testerType": "business",
  "idempotencyKey": "00000000-0000-4000-8000-000000000000"
}

Responses

201Tester registry created and workspace provisioning completed or left safely resumable.
Content-Type: application/json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "email": "user@example.com",
  "testerType": "string",
  "status": "string",
  "workspaceStatus": "ready",
  "failureCode": null,
  "workspaceLabel": "string",
  "updatedAt": "string"
}
400The tester request is invalid.
Content-Type: application/json
{
  "error": "string"
}
403Owner feature access or global superadmin authority is required.
Content-Type: application/json
{
  "error": "string"
}
409The idempotency key or tester identity conflicts with existing state.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/richmethods_owner_ops/beta-testers" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"testerType\": \"business\",
  \"idempotencyKey\": \"00000000-0000-4000-8000-000000000000\"
}"
POST/richmethods_owner_ops/beta-testers/{id}/access
Auth required

Suspend or revoke a beta tester's access

Sets the registry status first (deny-first), empties the dedicated beta role's feature grants, revokes the tester's customer sessions through the framework session service, and cancels the tester's TEST/DEMO subscriptions through the commerce status transition. No workspace, account, or history is deleted. Step outcomes are recorded on the registry row and returned; cleanupComplete is false when a step needs a retry, and re-running the same request retries only the unfinished steps.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Access suspended or revoked with recorded cleanup outcomes.
Content-Type: application/json
{
  "testerId": "00000000-0000-4000-8000-000000000000",
  "status": "suspended",
  "roleFeaturesCleared": true,
  "sessionsRevoked": true,
  "entitlements": [
    {
      "productKey": "string",
      "outcome": "string",
      "subscriptionId": null
    }
  ],
  "cleanupComplete": true,
  "updatedAt": "string"
}
400The tester id or the desired access state is invalid.
Content-Type: application/json
"string"
403Owner feature access or global superadmin authority is required.
Content-Type: application/json
"string"
404The tester is unavailable in the owner scope.
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/richmethods_owner_ops/beta-testers/:id/access" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/richmethods_owner_ops/beta-testers/{id}/cancel-invitation
Auth required

Cancel a pending beta tester invitation

Sets the framework invitation cancelledAt in the tester scope, so the framework accept path refuses the token from that moment on. The tester registry row and workspace are preserved; cancelling an already-cancelled invitation is idempotent.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Invitation cancelled (or already cancelled).
Content-Type: application/json
{
  "testerId": "00000000-0000-4000-8000-000000000000",
  "invitationId": "00000000-0000-4000-8000-000000000000",
  "outcome": "cancelled",
  "status": "string",
  "updatedAt": "string"
}
400The tester id is invalid.
Content-Type: application/json
"string"
403Owner feature access or global superadmin authority is required.
Content-Type: application/json
"string"
404The tester is unavailable in the owner scope.
Content-Type: application/json
"string"
409There is no pending invitation, or it was already accepted or expired.
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/richmethods_owner_ops/beta-testers/:id/cancel-invitation" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/richmethods_owner_ops/beta-testers/{id}/grant-access
Auth required

Grant or re-grant a beta tester's access

Ensures the dedicated per-tester customer role in the tester organization, sets its ACL to the owner-selected feature IDs (wildcards rejected), links the accepted customer account when present, and creates the selected TEST/DEMO product entitlements through the commerce TEST/DEMO checkout path, which never initiates payment. Omitting features/productKeys re-applies the selection stored on the registry row. Per-product outcomes are reported in the response.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Access granted with per-product entitlement outcomes.
Content-Type: application/json
{
  "testerId": "00000000-0000-4000-8000-000000000000",
  "roleId": "00000000-0000-4000-8000-000000000000",
  "roleCreated": true,
  "features": [
    "string"
  ],
  "entitlements": [
    {
      "productKey": "string",
      "outcome": "string",
      "subscriptionId": null
    }
  ],
  "customerUserId": null,
  "customerUserLinked": true,
  "status": "string",
  "updatedAt": "string"
}
400The tester id or the grant selection is invalid.
Content-Type: application/json
"string"
403Owner feature access or global superadmin authority is required.
Content-Type: application/json
"string"
404The tester is unavailable in the owner scope.
Content-Type: application/json
"string"
409The tester workspace is not ready, or the tester is revoked.
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/richmethods_owner_ops/beta-testers/:id/grant-access" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/richmethods_owner_ops/beta-testers/{id}/invite
Auth required

Create or resend a beta tester invitation

Creates the framework customer invitation in the tester tenant/organization scope and records it on the registry row. Re-inviting a still-pending tester rotates the token and extends the 72-hour expiry (the framework resend behavior). After the invitation commits, the invitation email is delivered through the framework mail transport; the response reports the delivery outcome (`sent` or `not_configured` when no mail transport is configured). If delivery is configured but the send fails, the invitation is rolled back and the route returns 502. The raw token is never returned.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

201Invitation recorded on the tester registry, with the email delivery outcome.
Content-Type: application/json
{
  "testerId": "00000000-0000-4000-8000-000000000000",
  "invitationId": "00000000-0000-4000-8000-000000000000",
  "email": "user@example.com",
  "status": "string",
  "reused": true,
  "expiresAt": "string",
  "updatedAt": "string"
}
400The tester id is invalid.
Content-Type: application/json
"string"
403Owner feature access or global superadmin authority is required.
Content-Type: application/json
"string"
404The tester is unavailable in the owner scope.
Content-Type: application/json
"string"
409The tester workspace is not ready or the tester cannot be invited.
Content-Type: application/json
"string"
502Invitation email delivery was configured but failed; the invitation was rolled back.
Content-Type: application/json
"string"

Example

curl -X POST "http://108.165.128.56:3000/api/richmethods_owner_ops/beta-testers/:id/invite" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/richmethods_owner_ops/health
Auth required

Get owner-only system health

Evidence-based status per system, incidents, and the customer-safe projection preview.

Responses

200Success.
Content-Type: application/json
{}
401Authentication required.
Content-Type: application/json
{
  "error": "string"
}
403Owner access required.
Content-Type: application/json
{
  "error": "string"
}
409The record changed; reload and retry.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_owner_ops/health" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/richmethods_owner_ops/health/override
Auth required

Set maintenance or disabled state

Owner-declared state; audited.

Request body (application/json)

{
  "checkKey": "string"
}

Responses

200Success.
Content-Type: application/json
{}
401Authentication required.
Content-Type: application/json
{
  "error": "string"
}
403Owner access required.
Content-Type: application/json
{
  "error": "string"
}
409The record changed; reload and retry.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/richmethods_owner_ops/health/override" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"checkKey\": \"string\"
}"
POST/richmethods_owner_ops/health/run
Auth required

Run one check or a full sweep

Runs lightweight probes and reconciles incidents.

Request body (application/json)

{}

Responses

200Success.
Content-Type: application/json
{}
401Authentication required.
Content-Type: application/json
{
  "error": "string"
}
403Owner access required.
Content-Type: application/json
{
  "error": "string"
}
409The record changed; reload and retry.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/richmethods_owner_ops/health/run" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{}"
POST/richmethods_owner_ops/incidents/action
Auth required

Acknowledge, approve, or run recovery

Risky recovery requires a prior owner approval; resolution requires verified recovery.

Request body (application/json)

{
  "id": "00000000-0000-4000-8000-000000000000",
  "action": "acknowledge",
  "expectedUpdatedAt": null
}

Responses

200Success.
Content-Type: application/json
{}
401Authentication required.
Content-Type: application/json
{
  "error": "string"
}
403Owner access required.
Content-Type: application/json
{
  "error": "string"
}
409The record changed; reload and retry.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/richmethods_owner_ops/incidents/action" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"action\": \"acknowledge\",
  \"expectedUpdatedAt\": null
}"
GET/richmethods_owner_ops/setup
Auth required

Get the owner setup board

Needs My Attention queue, readiness, and every setup requirement. Never returns secrets.

Responses

200Setup board.
Content-Type: application/json
{}
401Authentication required.
Content-Type: application/json
{
  "error": "string"
}
403Owner access required.
Content-Type: application/json
{
  "error": "string"
}
409The record changed; reload and retry.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_owner_ops/setup" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/richmethods_owner_ops/setup/action
Auth required

Apply an owner setup action

Submit a credential reference (never a secret), mark external steps, approve, retry, or reconfigure.

Request body (application/json)

{
  "key": "string",
  "action": "submit",
  "credentialReference": null,
  "expectedUpdatedAt": null
}

Responses

200Success.
Content-Type: application/json
{}
401Authentication required.
Content-Type: application/json
{
  "error": "string"
}
403Owner access required.
Content-Type: application/json
{
  "error": "string"
}
409The record changed; reload and retry.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/richmethods_owner_ops/setup/action" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"key\": \"string\",
  \"action\": \"submit\",
  \"credentialReference\": null,
  \"expectedUpdatedAt\": null
}"
GET/richmethods_owner_ops/team-access
Auth required

List worker profiles

Returns the workers the authenticated owner administers in the current owner scope, with their saved access matrix.

Responses

200Worker list.
Content-Type: application/json
{
  "name": "string",
  "email": "user@example.com",
  "password": "string",
  "homeOrganizationId": "00000000-0000-4000-8000-000000000000",
  "template": "custom"
}
401Authentication required.
Content-Type: application/json
{
  "error": "string"
}
403Owner access required.
Content-Type: application/json
{
  "error": "string"
}
409The record changed; reload and retry.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_owner_ops/team-access" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/richmethods_owner_ops/team-access
Auth required

Create a worker profile

Creates a staff user with a dedicated role whose ACL is exactly the chosen template/matrix. New profiles start from the template (Custom = no access anywhere).

Responses

201Created worker.
Content-Type: application/json
{
  "name": "string",
  "email": "user@example.com",
  "password": "string",
  "homeOrganizationId": "00000000-0000-4000-8000-000000000000",
  "template": "custom"
}
401Authentication required.
Content-Type: application/json
{
  "error": "string"
}
403Owner access required.
Content-Type: application/json
{
  "error": "string"
}
409The record changed; reload and retry.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/richmethods_owner_ops/team-access" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/richmethods_owner_ops/team-access/{id}/access
Auth required

Replace a worker access matrix

Replaces the saved matrix (and optional extra organization grants); the worker role ACL is rewritten from the matrix and the RBAC cache is invalidated so the change applies immediately.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Updated worker.
Content-Type: application/json
{
  "matrix": {
    "clients": "none",
    "money": "none",
    "marketing": "none",
    "reports": "none",
    "settings": "none"
  }
}
401Authentication required.
Content-Type: application/json
{
  "error": "string"
}
403Owner access required.
Content-Type: application/json
{
  "error": "string"
}
409The record changed; reload and retry.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/richmethods_owner_ops/team-access/:id/access" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/richmethods_owner_ops/team-access/{id}/status
Auth required

Deactivate or reactivate a worker

Deactivation empties the role ACL, deletes live sessions, and soft-deletes the staff user so access dies immediately; reactivation restores the saved matrix.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Updated worker.
Content-Type: application/json
{
  "status": "active"
}
401Authentication required.
Content-Type: application/json
{
  "error": "string"
}
403Owner access required.
Content-Type: application/json
{
  "error": "string"
}
409The record changed; reload and retry.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/richmethods_owner_ops/team-access/:id/status" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
GET/richmethods_owner_ops/team-access/events
Auth required

List Team & Access activity

Access changes recorded by the owner admin location: who changed whose access, when, and what changed.

Responses

200Activity list.
Content-Type: application/json
"string"
401Authentication required.
Content-Type: application/json
{
  "error": "string"
}
403Owner access required.
Content-Type: application/json
{
  "error": "string"
}
409The record changed; reload and retry.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_owner_ops/team-access/events" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"

Rich Methods Workforce

Showing 11 of 11 endpoints
GET/richmethods_workforce/assignments
Auth required

List workforce assignments

Lists paginated tenant- and organization-scoped AI workforce assignments.

Parameters

NameInRequiredSchemaDescription
idqueryNoany—
assistantIdqueryNoany—
statusqueryNoany—
jobTemplateIdqueryNoany—
assignmentTypequeryNoany—
pagequeryNoany—
pageSizequeryNoany—

Responses

200Scoped workforce assignments.
Content-Type: application/json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "assistantId": "00000000-0000-4000-8000-000000000000",
      "assistantName": "string",
      "jobTemplateId": "string",
      "jobTemplateTitle": "string",
      "jobTemplateVersion": 1,
      "requestGroupId": "00000000-0000-4000-8000-000000000000",
      "seatIndex": 1,
      "requestedQuantity": 1,
      "assignmentType": "permanent",
      "status": "draft",
      "effectiveStatus": "draft",
      "startAt": "string",
      "endAt": null,
      "endCondition": null,
      "supervisorUserId": null,
      "capabilitySnapshot": [
        "string"
      ],
      "recipeTemplateKeys": [
        "string"
      ],
      "requiredConnections": [
        "string"
      ],
      "approvalPolicy": "string",
      "readinessIssues": [
        "string"
      ],
      "createdAt": "string",
      "updatedAt": "string"
    }
  ],
  "total": 1,
  "totalPages": 1
}
403The current user cannot view workforce assignments.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_workforce/assignments?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/richmethods_workforce/assignments
Auth required

Request workforce staff

Atomically creates one assistant and assignment per requested seat. Requests are idempotent and never activate a worker.

Request body (application/json)

{
  "requestIdempotencyKey": "00000000-0000-4000-8000-000000000000",
  "jobTemplateId": "administrative_assistant",
  "assignmentType": "permanent",
  "quantity": 1,
  "startAt": "string",
  "endAt": null,
  "endCondition": null,
  "supervisorUserId": "00000000-0000-4000-8000-000000000000",
  "approvalPolicy": "human_approval"
}

Responses

201Requested workforce assignments.
Content-Type: application/json
{
  "requestGroupId": "00000000-0000-4000-8000-000000000000",
  "duplicate": true,
  "assignments": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "assistantId": "00000000-0000-4000-8000-000000000000",
      "assistantName": "string",
      "jobTemplateId": "string",
      "jobTemplateTitle": "string",
      "jobTemplateVersion": 1,
      "requestGroupId": "00000000-0000-4000-8000-000000000000",
      "seatIndex": 1,
      "requestedQuantity": 1,
      "assignmentType": "permanent",
      "status": "draft",
      "effectiveStatus": "draft",
      "startAt": "string",
      "endAt": null,
      "endCondition": null,
      "supervisorUserId": null,
      "capabilitySnapshot": [
        "string"
      ],
      "recipeTemplateKeys": [
        "string"
      ],
      "requiredConnections": [
        "string"
      ],
      "approvalPolicy": "string",
      "readinessIssues": [
        "string"
      ],
      "createdAt": "string",
      "updatedAt": "string"
    }
  ]
}
400The request is invalid or exceeds the selected product capability.
Content-Type: application/json
{
  "error": "string"
}
403The current user cannot request staff or the supervisor is outside the current organization.
Content-Type: application/json
{
  "error": "string"
}
409The request idempotency key conflicts with a prior request.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/richmethods_workforce/assignments" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"requestIdempotencyKey\": \"00000000-0000-4000-8000-000000000000\",
  \"jobTemplateId\": \"administrative_assistant\",
  \"assignmentType\": \"permanent\",
  \"quantity\": 1,
  \"startAt\": \"string\",
  \"endAt\": null,
  \"endCondition\": null,
  \"supervisorUserId\": \"00000000-0000-4000-8000-000000000000\",
  \"approvalPolicy\": \"human_approval\"
}"
PUT/richmethods_workforce/assignments
Auth required

Change workforce assignment lifecycle

Performs an explicitly authorized, optimistic-locked assignment action; ending or pausing immediately denies execution.

Request body (application/json)

{
  "id": "00000000-0000-4000-8000-000000000000",
  "updatedAt": "string",
  "action": "activate"
}

Responses

200Updated assignment.
Content-Type: application/json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "assistantId": "00000000-0000-4000-8000-000000000000",
  "assistantName": "string",
  "jobTemplateId": "string",
  "jobTemplateTitle": "string",
  "jobTemplateVersion": 1,
  "requestGroupId": "00000000-0000-4000-8000-000000000000",
  "seatIndex": 1,
  "requestedQuantity": 1,
  "assignmentType": "permanent",
  "status": "draft",
  "effectiveStatus": "draft",
  "startAt": "string",
  "endAt": null,
  "endCondition": null,
  "supervisorUserId": null,
  "capabilitySnapshot": [
    "string"
  ],
  "recipeTemplateKeys": [
    "string"
  ],
  "requiredConnections": [
    "string"
  ],
  "approvalPolicy": "string",
  "readinessIssues": [
    "string"
  ],
  "createdAt": "string",
  "updatedAt": "string"
}
400The action is invalid.
Content-Type: application/json
{
  "error": "string"
}
403The current user cannot manage workforce assignments.
Content-Type: application/json
{
  "error": "string"
}
404The assignment is not available in the current scope.
Content-Type: application/json
{
  "error": "string"
}
409The assignment changed or is not ready for this action.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X PUT "http://108.165.128.56:3000/api/richmethods_workforce/assignments" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"updatedAt\": \"string\",
  \"action\": \"activate\"
}"
GET/richmethods_workforce/assignments/{id}
Auth required

Get a workforce assignment

Returns a single assignment only when it belongs to the authenticated tenant and organization.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200The scoped assignment.
Content-Type: application/json
"string"
400Invalid assignment ID.
Content-Type: application/json
{
  "error": "string"
}
403The current user cannot view workforce assignments.
Content-Type: application/json
{
  "error": "string"
}
404The assignment is unavailable in the current scope.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_workforce/assignments/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
PUT/richmethods_workforce/assignments/{id}
Auth required

Change workforce assignment lifecycle

Performs a lifecycle action on the path assignment using its current updatedAt version.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Request body (application/json)

{
  "id": "00000000-0000-4000-8000-000000000000",
  "updatedAt": "string",
  "action": "activate"
}

Responses

200The updated scoped assignment.
Content-Type: application/json
"string"
400Invalid action or assignment ID.
Content-Type: application/json
{
  "error": "string"
}
403The current user cannot manage workforce assignments.
Content-Type: application/json
{
  "error": "string"
}
404The assignment is unavailable in the current scope.
Content-Type: application/json
{
  "error": "string"
}
409The assignment changed or is not ready for this action.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X PUT "http://108.165.128.56:3000/api/richmethods_workforce/assignments/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"updatedAt\": \"string\",
  \"action\": \"activate\"
}"
POST/richmethods_workforce/assistant-sessions
Auth required

Create an assistant session

Creates a short-lived, server-bound native AI session for an active assistant.

Request body (application/json)

{
  "assistantId": "00000000-0000-4000-8000-000000000000"
}

Responses

201Created and scoped assistant session.
Content-Type: application/json
{
  "assistantId": "00000000-0000-4000-8000-000000000000",
  "sessionId": "00000000-0000-4000-8000-000000000000",
  "agentId": "string",
  "expiresAt": "string"
}
400Invalid assistant session request.
Content-Type: application/json
{
  "error": "string"
}
403The current user is not authorized to execute assistants.
Content-Type: application/json
{
  "error": "string"
}
404The assistant is unavailable in the current scope.
Content-Type: application/json
{
  "error": "string"
}
409The assistant is not configured for execution.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/richmethods_workforce/assistant-sessions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"assistantId\": \"00000000-0000-4000-8000-000000000000\"
}"
GET/richmethods_workforce/assistants
Auth required

List ai assistants

Returns a paginated collection of ai assistants in the current tenant and organization scope.

Parameters

NameInRequiredSchemaDescription
idqueryNoany—
searchqueryNoany—
pagequeryNoany—
pageSizequeryNoany—
statusqueryNoany—
jobTemplateIdqueryNoany—
sortFieldqueryNoany—
sortDirqueryNoany—
idsqueryNoanyComma-separated list of record UUIDs to filter by (max 200).

Responses

200Paginated ai assistants
Content-Type: application/json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "display_name": "string",
      "job_template_id": "string",
      "description": null,
      "status": "draft",
      "technical_agent_id": null,
      "supervisor_user_id": null,
      "capability_ids": [
        "string"
      ],
      "autonomy_level": "observe",
      "approval_policy": "require_human",
      "escalation_rules": {
        "approvalRequired": true,
        "insufficientPermission": true,
        "unsupportedCapability": true,
        "missingIntegration": true,
        "highRiskOrUncertain": true
      },
      "created_at": "string",
      "updated_at": "string"
    }
  ],
  "total": 1,
  "totalPages": 1
}

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_workforce/assistants?page=1&pageSize=50&sortField=updated_at&sortDir=desc" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
POST/richmethods_workforce/assistants
Auth required

Create ai assistant

Creates a workforce assistant in the current tenant and organization.

Request body (application/json)

{
  "displayName": "string",
  "jobTemplateId": "administrative_assistant",
  "description": null,
  "status": "draft",
  "supervisorUserId": null,
  "autonomyLevel": "observe",
  "approvalPolicy": "require_human",
  "escalationRules": {
    "approvalRequired": true,
    "insufficientPermission": true,
    "unsupportedCapability": true,
    "missingIntegration": true,
    "highRiskOrUncertain": true
  }
}

Responses

201AI assistant created
Content-Type: application/json
{
  "id": "00000000-0000-4000-8000-000000000000"
}

Example

curl -X POST "http://108.165.128.56:3000/api/richmethods_workforce/assistants" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"displayName\": \"string\",
  \"jobTemplateId\": \"administrative_assistant\",
  \"description\": null,
  \"status\": \"draft\",
  \"supervisorUserId\": null,
  \"autonomyLevel\": \"observe\",
  \"approvalPolicy\": \"require_human\",
  \"escalationRules\": {
    \"approvalRequired\": true,
    \"insufficientPermission\": true,
    \"unsupportedCapability\": true,
    \"missingIntegration\": true,
    \"highRiskOrUncertain\": true
  }
}"
PUT/richmethods_workforce/assistants
Auth required

Update ai assistant

Updates a workforce assistant using its optimistic-lock version.

Request body (application/json)

{
  "id": "00000000-0000-4000-8000-000000000000",
  "updatedAt": "string",
  "description": null,
  "supervisorUserId": null
}

Responses

200AI assistant updated
Content-Type: application/json
{
  "ok": true
}

Example

curl -X PUT "http://108.165.128.56:3000/api/richmethods_workforce/assistants" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"updatedAt\": \"string\",
  \"description\": null,
  \"supervisorUserId\": null
}"
DELETE/richmethods_workforce/assistants
Auth required

Delete ai assistant

Soft-deletes a workforce assistant and revokes bound sessions.

Request body (application/json)

{
  "id": "00000000-0000-4000-8000-000000000000",
  "updatedAt": "string"
}

Responses

200AI assistant deleted
Content-Type: application/json
{
  "ok": true
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/richmethods_workforce/assistants" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"updatedAt\": \"string\"
}"
GET/richmethods_workforce/catalog
Auth required

Get workforce catalogs

Returns versioned job products, non-priced Self-Setup and Done-For-You implementation modes, bounded capabilities, capability packages and declarative future integration requirements. Marketing advertising metadata does not connect accounts or authorize spend.

Responses

200The workforce catalogs.
Content-Type: application/json
{
  "templates": [
    {
      "id": "string",
      "title": "string",
      "description": "string",
      "customerDescription": "string",
      "category": "general_business",
      "responsibilities": [
        "string"
      ],
      "capabilityPackageIds": [
        "string"
      ],
      "defaultCapabilityIds": [
        "string"
      ],
      "optionalCapabilityIds": [
        "string"
      ],
      "prohibitedCapabilityIds": [
        "string"
      ],
      "defaultRecipeTemplateKeys": [
        "string"
      ],
      "requiredConnections": [
        {
          "id": "string",
          "required": true,
          "description": "string",
          "phase": 6
        }
      ],
      "optionalConnections": [
        {
          "id": "string",
          "required": true,
          "description": "string",
          "phase": 6
        }
      ],
      "communicationChannels": [
        "string"
      ],
      "approvalDefault": "human_approval",
      "supervisorRequired": true,
      "escalationRules": [
        "string"
      ],
      "recommendedAssignmentTypes": [
        "string"
      ],
      "implementationModes": [
        {
          "id": "self_setup",
          "customerResponsibilities": [
            "string"
          ],
          "richMethodsResponsibilities": [
            "string"
          ],
          "ownerApprovalGates": [
            "string"
          ]
        }
      ],
      "instructions": "string",
      "version": 1,
      "status": "active",
      "technicalAgentId": "string"
    }
  ],
  "capabilities": [
    {
      "id": "string",
      "name": "string",
      "description": "string",
      "tools": [
        "string"
      ],
      "requiredFeatures": [
        "string"
      ],
      "mutationPosture": "read_only",
      "approvalRequired": true,
      "externalIntegrationRequired": true
    }
  ],
  "capabilityPackages": [
    {
      "id": "string",
      "title": "string",
      "description": "string",
      "capabilityIds": [
        "string"
      ]
    }
  ]
}
401Authentication required.
Content-Type: application/json
{
  "error": "string"
}
403The current user cannot view workforce catalogs.
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/richmethods_workforce/catalog" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"

Workflows

Showing 20 of 56 endpoints
GET/workflows/command-settings
Auth required

List workflow-safe command candidates with tenant enablement

Returns every command declared through registerWorkflowSafeCommands together with whether this tenant has switched it on. `configured: false` means the tenant has never saved the setting and the answers come from the grandfathered defaults.

Responses

200Catalogue with tenant enablement
Content-Type: application/json
{
  "configured": true,
  "items": [
    {
      "commandId": "string",
      "requiredFeatures": [
        "string"
      ],
      "labelKey": null
    }
  ]
}
401Missing authentication
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/workflows/command-settings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
PUT/workflows/command-settings
Auth required

Set which workflow-safe commands are enabled for the tenant

Replaces the tenant's enabled set. Every submitted id must be present in the code-declared catalogue; an unknown id is rejected with 400 rather than stored. Stored ids whose declaring module is not loaded in this process are retained so a save can never silently untick them.

Request body (application/json)

{
  "enabledCommandIds": [
    "string"
  ]
}

Responses

200Updated enablement
Content-Type: application/json
{
  "configured": true,
  "items": [
    {
      "commandId": "string",
      "requiredFeatures": [
        "string"
      ],
      "labelKey": null
    }
  ],
  "ok": true
}
400Invalid payload or unknown command id
Content-Type: application/json
{
  "error": "string"
}
401Missing authentication
Content-Type: application/json
{
  "error": "string"
}
503Settings storage unavailable
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X PUT "http://108.165.128.56:3000/api/workflows/command-settings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"enabledCommandIds\": [
    \"string\"
  ]
}"
GET/workflows/commands

List commands allowlisted for UPDATE_ENTITY activities

Returns the registered workflow-safe command catalogue consumed by the UPDATE_ENTITY command picker, each entry carrying whether the caller's tenant has enabled it. Entries with enabled:false, and commands outside the catalogue entirely, can still be authored but fail at runtime.

Responses

200Allowlisted workflow-safe commands
Content-Type: application/json
{
  "items": [
    {
      "commandId": "string",
      "requiredFeatures": [
        "string"
      ],
      "labelKey": null
    }
  ]
}
400Missing tenant context
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
403Insufficient permissions
Content-Type: application/json
{
  "error": "string"
}
500Internal server error
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/workflows/commands" \
  -H "Accept: application/json"
GET/workflows/definitions

List workflow definitions

Get a list of workflow definitions with optional filters. Supports pagination and search.

Parameters

NameInRequiredSchemaDescription
workflowIdqueryYesany—
enabledqueryNoany—
searchqueryNoany—
limitqueryNoany—
offsetqueryNoany—

Responses

200List of workflow definitions with pagination
Content-Type: application/json
{
  "data": [
    {
      "id": "123e4567-e89b-12d3-a456-426614174000",
      "workflowId": "checkout-flow",
      "workflowName": "Checkout Flow",
      "description": "Complete checkout workflow for processing orders",
      "version": 1,
      "definition": {
        "steps": [
          {
            "stepId": "start",
            "stepName": "Start",
            "stepType": "START"
          },
          {
            "stepId": "validate-cart",
            "stepName": "Validate Cart",
            "stepType": "AUTOMATED"
          },
          {
            "stepId": "end",
            "stepName": "End",
            "stepType": "END"
          }
        ],
        "transitions": [
          {
            "transitionId": "start-to-validate",
            "fromStepId": "start",
            "toStepId": "validate-cart",
            "trigger": "auto"
          },
          {
            "transitionId": "validate-to-end",
            "fromStepId": "validate-cart",
            "toStepId": "end",
            "trigger": "auto"
          }
        ]
      },
      "enabled": true,
      "tenantId": "123e4567-e89b-12d3-a456-426614174001",
      "organizationId": "123e4567-e89b-12d3-a456-426614174002",
      "createdAt": "2025-12-08T10:00:00.000Z",
      "updatedAt": "2025-12-08T10:00:00.000Z"
    }
  ],
  "pagination": {
    "total": 1,
    "limit": 50,
    "offset": 0,
    "hasMore": false
  }
}

Example

curl -X GET "http://108.165.128.56:3000/api/workflows/definitions?workflowId=string&limit=50&offset=0" \
  -H "Accept: application/json"
POST/workflows/definitions

Create workflow definition

Create a new workflow definition. The definition must include at least START and END steps with at least one transition connecting them.

Request body (application/json)

{
  "workflowId": "checkout-flow",
  "workflowName": "Checkout Flow",
  "description": "Complete checkout workflow for processing orders",
  "version": 1,
  "definition": {
    "steps": [
      {
        "stepId": "start",
        "stepName": "Start",
        "stepType": "START"
      },
      {
        "stepId": "validate-cart",
        "stepName": "Validate Cart",
        "stepType": "AUTOMATED",
        "description": "Validate cart items and check inventory"
      },
      {
        "stepId": "payment",
        "stepName": "Process Payment",
        "stepType": "AUTOMATED",
        "description": "Charge payment method",
        "retryPolicy": {
          "maxAttempts": 3,
          "backoffMs": 1000
        }
      },
      {
        "stepId": "end",
        "stepName": "End",
        "stepType": "END"
      }
    ],
    "transitions": [
      {
        "transitionId": "start-to-validate",
        "fromStepId": "start",
        "toStepId": "validate-cart",
        "trigger": "auto"
      },
      {
        "transitionId": "validate-to-payment",
        "fromStepId": "validate-cart",
        "toStepId": "payment",
        "trigger": "auto"
      },
      {
        "transitionId": "payment-to-end",
        "fromStepId": "payment",
        "toStepId": "end",
        "trigger": "auto",
        "activities": [
          {
            "activityName": "Send Order Confirmation",
            "activityType": "SEND_EMAIL",
            "config": {
              "to": "{{context.customerEmail}}",
              "subject": "Order Confirmation #{{context.orderId}}",
              "template": "order_confirmation"
            }
          }
        ]
      }
    ]
  },
  "enabled": true
}

Responses

201Workflow definition created successfully
Content-Type: application/json
{
  "data": {
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "workflowId": "checkout-flow",
    "workflowName": "Checkout Flow",
    "description": "Complete checkout workflow for processing orders",
    "version": 1,
    "definition": {
      "steps": [
        {
          "stepId": "start",
          "stepName": "Start",
          "stepType": "START"
        },
        {
          "stepId": "validate-cart",
          "stepName": "Validate Cart",
          "stepType": "AUTOMATED"
        },
        {
          "stepId": "payment",
          "stepName": "Process Payment",
          "stepType": "AUTOMATED"
        },
        {
          "stepId": "end",
          "stepName": "End",
          "stepType": "END"
        }
      ],
      "transitions": [
        {
          "transitionId": "start-to-validate",
          "fromStepId": "start",
          "toStepId": "validate-cart",
          "trigger": "auto"
        },
        {
          "transitionId": "validate-to-payment",
          "fromStepId": "validate-cart",
          "toStepId": "payment",
          "trigger": "auto"
        },
        {
          "transitionId": "payment-to-end",
          "fromStepId": "payment",
          "toStepId": "end",
          "trigger": "auto"
        }
      ]
    },
    "enabled": true,
    "tenantId": "123e4567-e89b-12d3-a456-426614174001",
    "organizationId": "123e4567-e89b-12d3-a456-426614174002",
    "createdAt": "2025-12-08T10:00:00.000Z",
    "updatedAt": "2025-12-08T10:00:00.000Z"
  },
  "message": "Workflow definition created successfully"
}
400Validation error - invalid workflow structure
Content-Type: application/json
{
  "error": "Validation failed",
  "details": [
    {
      "path": [
        "definition",
        "steps"
      ],
      "code": "custom",
      "message": "Workflow must have at least START and END steps"
    }
  ]
}
409Conflict - workflow with same ID and version already exists
Content-Type: application/json
{
  "error": "Workflow definition with ID \"checkout-flow\" and version 1 already exists"
}

Example

curl -X POST "http://108.165.128.56:3000/api/workflows/definitions" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"workflowId\": \"string\",
  \"workflowName\": \"string\",
  \"description\": null,
  \"version\": 1,
  \"definition\": {
    \"steps\": [
      {
        \"stepId\": \"string\",
        \"stepName\": \"string\",
        \"stepType\": \"START\"
      }
    ],
    \"transitions\": [
      {
        \"transitionId\": \"string\",
        \"fromStepId\": \"string\",
        \"toStepId\": \"string\",
        \"trigger\": \"auto\",
        \"condition\": null,
        \"continueOnActivityFailure\": false,
        \"priority\": 0
      }
    ]
  },
  \"metadata\": null,
  \"enabled\": true,
  \"grantedFeatures\": null
}"
GET/workflows/definitions/{id}

Get workflow definition

Get a single workflow definition by ID. Returns the complete workflow structure including steps and transitions (with embedded activities).

Parameters

NameInRequiredSchemaDescription
idpathYesanyUUID for DB definitions, or "code:<workflowId>" for code-based definitions

Responses

200Workflow definition found
Content-Type: application/json
{
  "data": {
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "workflowId": "checkout-flow",
    "workflowName": "Checkout Flow",
    "description": "Complete checkout workflow for processing orders",
    "version": 1,
    "definition": {
      "steps": [
        {
          "stepId": "start",
          "stepName": "Start",
          "stepType": "START"
        },
        {
          "stepId": "validate-cart",
          "stepName": "Validate Cart",
          "stepType": "AUTOMATED",
          "description": "Validate cart items and check inventory"
        },
        {
          "stepId": "payment",
          "stepName": "Process Payment",
          "stepType": "AUTOMATED",
          "description": "Charge payment method",
          "retryPolicy": {
            "maxAttempts": 3,
            "backoffMs": 1000
          }
        },
        {
          "stepId": "end",
          "stepName": "End",
          "stepType": "END"
        }
      ],
      "transitions": [
        {
          "transitionId": "start-to-validate",
          "fromStepId": "start",
          "toStepId": "validate-cart",
          "trigger": "auto"
        },
        {
          "transitionId": "validate-to-payment",
          "fromStepId": "validate-cart",
          "toStepId": "payment",
          "trigger": "auto"
        },
        {
          "transitionId": "payment-to-end",
          "fromStepId": "payment",
          "toStepId": "end",
          "trigger": "auto",
          "activities": [
            {
              "activityName": "Send Order Confirmation",
              "activityType": "SEND_EMAIL",
              "config": {
                "to": "{{context.customerEmail}}",
                "subject": "Order Confirmation #{{context.orderId}}",
                "template": "order_confirmation"
              }
            }
          ]
        }
      ]
    },
    "enabled": true,
    "tenantId": "123e4567-e89b-12d3-a456-426614174001",
    "organizationId": "123e4567-e89b-12d3-a456-426614174002",
    "createdAt": "2025-12-08T10:00:00.000Z",
    "updatedAt": "2025-12-08T10:00:00.000Z"
  }
}
404Workflow definition not found
Content-Type: application/json
{
  "error": "Workflow definition not found"
}

Example

curl -X GET "http://108.165.128.56:3000/api/workflows/definitions/string" \
  -H "Accept: application/json"
PUT/workflows/definitions/{id}

Update workflow definition

Update an existing workflow definition. Supports partial updates - only provided fields will be updated.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Request body (application/json)

{
  "definition": {
    "steps": [
      {
        "stepId": "start",
        "stepName": "Start",
        "stepType": "START"
      },
      {
        "stepId": "validate-cart",
        "stepName": "Validate Cart",
        "stepType": "AUTOMATED"
      },
      {
        "stepId": "payment",
        "stepName": "Process Payment",
        "stepType": "AUTOMATED"
      },
      {
        "stepId": "confirmation",
        "stepName": "Order Confirmation",
        "stepType": "AUTOMATED"
      },
      {
        "stepId": "end",
        "stepName": "End",
        "stepType": "END"
      }
    ],
    "transitions": [
      {
        "transitionId": "start-to-validate",
        "fromStepId": "start",
        "toStepId": "validate-cart",
        "trigger": "auto"
      },
      {
        "transitionId": "validate-to-payment",
        "fromStepId": "validate-cart",
        "toStepId": "payment",
        "trigger": "auto"
      },
      {
        "transitionId": "payment-to-confirmation",
        "fromStepId": "payment",
        "toStepId": "confirmation",
        "trigger": "auto"
      },
      {
        "transitionId": "confirmation-to-end",
        "fromStepId": "confirmation",
        "toStepId": "end",
        "trigger": "auto"
      }
    ]
  },
  "enabled": true
}

Responses

200Workflow definition updated successfully
Content-Type: application/json
{
  "data": {
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "workflowId": "checkout-flow",
    "workflowName": "Checkout Flow",
    "description": "Complete checkout workflow for processing orders",
    "version": 1,
    "definition": {
      "steps": [
        {
          "stepId": "start",
          "stepName": "Start",
          "stepType": "START"
        },
        {
          "stepId": "validate-cart",
          "stepName": "Validate Cart",
          "stepType": "AUTOMATED"
        },
        {
          "stepId": "payment",
          "stepName": "Process Payment",
          "stepType": "AUTOMATED"
        },
        {
          "stepId": "confirmation",
          "stepName": "Order Confirmation",
          "stepType": "AUTOMATED"
        },
        {
          "stepId": "end",
          "stepName": "End",
          "stepType": "END"
        }
      ],
      "transitions": [
        {
          "transitionId": "start-to-validate",
          "fromStepId": "start",
          "toStepId": "validate-cart",
          "trigger": "auto"
        },
        {
          "transitionId": "validate-to-payment",
          "fromStepId": "validate-cart",
          "toStepId": "payment",
          "trigger": "auto"
        },
        {
          "transitionId": "payment-to-confirmation",
          "fromStepId": "payment",
          "toStepId": "confirmation",
          "trigger": "auto"
        },
        {
          "transitionId": "confirmation-to-end",
          "fromStepId": "confirmation",
          "toStepId": "end",
          "trigger": "auto"
        }
      ]
    },
    "enabled": true,
    "tenantId": "123e4567-e89b-12d3-a456-426614174001",
    "organizationId": "123e4567-e89b-12d3-a456-426614174002",
    "createdAt": "2025-12-08T10:00:00.000Z",
    "updatedAt": "2025-12-08T11:30:00.000Z"
  },
  "message": "Workflow definition updated successfully"
}
400Validation error
Content-Type: application/json
{
  "error": "Validation failed",
  "details": [
    {
      "path": [
        "definition"
      ],
      "code": "invalid_type",
      "message": "Invalid input: expected object, received string",
      "expected": "object",
      "got": "string"
    }
  ]
}
404Workflow definition not found
Content-Type: application/json
{
  "error": "Workflow definition not found"
}
409Structural change refused while instances are still running (or optimistic-lock conflict). Publish a new version and apply the change there.
Content-Type: application/json
{
  "error": "Structural changes require a new version while instances are still running",
  "code": "WORKFLOW_STRUCTURAL_EDIT_REQUIRES_NEW_VERSION",
  "definitionId": "123e4567-e89b-12d3-a456-426614174000",
  "activeInstanceCount": 3,
  "activeStatuses": [
    "RUNNING",
    "PAUSED",
    "WAITING_FOR_ACTIVITIES",
    "FORKED",
    "COMPENSATING"
  ],
  "changes": [
    {
      "kind": "transitionRetargeted",
      "id": "t_lz3k9_ab12cd34e"
    }
  ],
  "remedy": {
    "action": "createVersion",
    "method": "POST",
    "endpoint": "/api/workflows/definitions/123e4567-e89b-12d3-a456-426614174000/publish"
  }
}

Example

curl -X PUT "http://108.165.128.56:3000/api/workflows/definitions/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"description\": null,
  \"metadata\": null,
  \"effectiveFrom\": null,
  \"effectiveTo\": null,
  \"grantedFeatures\": null
}"
DELETE/workflows/definitions/{id}

Delete workflow definition

Soft delete a workflow definition. Cannot be deleted if there are active workflow instances (RUNNING or WAITING status) using this definition.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Workflow definition deleted successfully
Content-Type: application/json
{
  "message": "Workflow definition deleted successfully"
}
404Workflow definition not found
Content-Type: application/json
{
  "error": "Workflow definition not found"
}
409Cannot delete - active workflow instances exist
Content-Type: application/json
{
  "error": "Cannot delete workflow definition with 3 active instance(s)"
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/workflows/definitions/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json"
GET/workflows/definitions/{id}/callers

List sub-workflow callers and breaking mappings

Returns parent definitions that invoke this workflow as a sub-workflow and the mappings its current port contract would break.

Parameters

NameInRequiredSchemaDescription
idpathYesanyWorkflow definition id

Responses

200Callers
Content-Type: application/json
{
  "callers": [
    {
      "workflowId": "order-flow",
      "version": 1,
      "stepId": "sub",
      "brokenMappings": [
        "input:orderId"
      ]
    }
  ]
}
404Not found
Content-Type: application/json
{
  "error": "Workflow definition not found"
}

Example

curl -X GET "http://108.165.128.56:3000/api/workflows/definitions/string/callers" \
  -H "Accept: application/json"
GET/workflows/definitions/{id}/context-schema

Get the per-step context ledger

Computes what context paths are available at each step of the workflow definition, with type, presence (always/maybe), and producer source. Presence degrades to "maybe" at joins unless the entry arrives on every incoming route. Use ?stepId=<id> to narrow the response to one step.

Parameters

NameInRequiredSchemaDescription
idpathYesanyUUID for DB definitions, or "code:<workflowId>" for code-based definitions
stepIdqueryNoanyNarrow the response to this step (404 when the step does not exist)

Responses

200Per-step context ledger
Content-Type: application/json
{
  "steps": {
    "approve": {
      "entries": [
        {
          "path": "orderId",
          "type": "text",
          "presence": "always",
          "source": {
            "kind": "contextSchema",
            "label": "contextSchema.input"
          }
        },
        {
          "path": "discount",
          "type": "number",
          "presence": "maybe",
          "source": {
            "kind": "userTask",
            "stepId": "review",
            "label": "userTask:review"
          }
        }
      ]
    }
  }
}
400Missing tenant context
Content-Type: application/json
{
  "error": "string"
}
403Insufficient permissions
Content-Type: application/json
{
  "error": "string"
}
404Workflow definition or requested step not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/workflows/definitions/string/context-schema" \
  -H "Accept: application/json"
POST/workflows/definitions/{id}/customize

Customize code-based workflow definition

Creates a DB override for a code-based workflow definition, seeded from the current code registry values. The id param must be of the form "code:<workflowId>".

Parameters

NameInRequiredSchemaDescription
idpathYesanyMust be of the form "code:<workflowId>"

Responses

200Workflow definition customized successfully
Content-Type: application/json
{
  "data": {
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "workflowId": "workflows.simple-approval",
    "workflowName": "Simple Approval Workflow",
    "source": "code_override"
  },
  "message": "Workflow definition customized successfully"
}
400Not a code-based id
Content-Type: application/json
{
  "error": "Customize is only supported for code-based workflow definitions"
}
404Code workflow not found
Content-Type: application/json
{
  "error": "Workflow definition not found"
}

Example

curl -X POST "http://108.165.128.56:3000/api/workflows/definitions/string/customize" \
  -H "Accept: application/json"
GET/workflows/definitions/{id}/draft

Get the current user's draft

Returns the authenticated user's autosaved draft for the workflow definition. Drafts are private to the user who saved them.

Parameters

NameInRequiredSchemaDescription
idpathYesanyWorkflow definition UUID (server drafts exist only for saved definitions)

Responses

200Draft found
Content-Type: application/json
{
  "data": {
    "id": "string",
    "definitionId": null,
    "definition": {
      "steps": [
        {}
      ],
      "transitions": [
        {}
      ]
    },
    "metadata": null,
    "baseUpdatedAt": null,
    "createdAt": null,
    "updatedAt": null
  }
}
400Invalid definition id (only saved definitions have server drafts)
Content-Type: application/json
{
  "error": "string"
}
403Insufficient permissions
Content-Type: application/json
{
  "error": "string"
}
404No draft exists for this user and definition
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/workflows/definitions/string/draft" \
  -H "Accept: application/json"
PUT/workflows/definitions/{id}/draft

Save the current user's draft

Creates or updates the authenticated user's draft for the workflow definition. The definition payload is validated shape-only (steps and transitions must be arrays of objects) so a mid-edit, structurally incomplete graph still saves; full validation runs when the draft is promoted via the definition PUT. Draft saves never participate in the definition's optimistic lock.

Parameters

NameInRequiredSchemaDescription
idpathYesanyWorkflow definition UUID (server drafts exist only for saved definitions)

Request body (application/json)

{
  "definition": {
    "steps": [
      {
        "stepId": "start",
        "stepName": "Start",
        "stepType": "START"
      }
    ],
    "transitions": []
  },
  "baseUpdatedAt": "2026-07-27T10:00:00.000Z"
}

Responses

200Draft saved
Content-Type: application/json
{
  "data": {
    "id": "string",
    "definitionId": null,
    "definition": {
      "steps": [
        {}
      ],
      "transitions": [
        {}
      ]
    },
    "metadata": null,
    "baseUpdatedAt": null,
    "createdAt": null,
    "updatedAt": null
  },
  "message": "string"
}
400Malformed draft payload or invalid definition id
Content-Type: application/json
{
  "error": "string"
}
403Insufficient permissions
Content-Type: application/json
{
  "error": "string"
}
404Workflow definition not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X PUT "http://108.165.128.56:3000/api/workflows/definitions/string/draft" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"definition\": {
    \"steps\": [
      {}
    ],
    \"transitions\": [
      {}
    ]
  },
  \"metadata\": null,
  \"baseUpdatedAt\": null
}"
DELETE/workflows/definitions/{id}/draft

Discard the current user's draft

Deletes the authenticated user's draft for the workflow definition. Idempotent: discarding a non-existent draft succeeds.

Parameters

NameInRequiredSchemaDescription
idpathYesanyWorkflow definition UUID (server drafts exist only for saved definitions)

Responses

200Draft discarded (or no draft existed)
Content-Type: application/json
{
  "message": "string"
}
400Invalid definition id
Content-Type: application/json
{
  "error": "string"
}
403Insufficient permissions
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X DELETE "http://108.165.128.56:3000/api/workflows/definitions/string/draft" \
  -H "Accept: application/json"
POST/workflows/definitions/{id}/publish

Publish a new workflow definition version

Mints a frozen published version snapshotting the definition and its IO port contract. Returns affected sub-workflow callers; pass acknowledgeBreakingChanges=true to publish despite breaking changes.

Parameters

NameInRequiredSchemaDescription
idpathYesanyWorkflow definition id

Request body (application/json)

"string"

Responses

200Published
Content-Type: application/json
{
  "data": {
    "id": "…",
    "workflowId": "verify-policy",
    "version": 2,
    "lifecycle": "published"
  },
  "breakingChanges": [],
  "message": "Workflow definition published successfully"
}
404Not found
Content-Type: application/json
{
  "error": "Workflow definition not found"
}
409Breaking changes not acknowledged
Content-Type: application/json
{
  "error": "Publishing would break existing sub-workflow mappings",
  "breakingChanges": [
    {
      "workflowId": "order-flow",
      "version": 1,
      "stepId": "sub",
      "brokenMappings": [
        "input:orderId"
      ]
    }
  ]
}

Example

curl -X POST "http://108.165.128.56:3000/api/workflows/definitions/string/publish" \
  -H "Accept: application/json"
POST/workflows/definitions/{id}/reset-to-code

Reset workflow definition to code version

Deletes the DB override for a code-based workflow definition, reverting it to the original code registry version. Cannot be reset if there are active instances.

Parameters

NameInRequiredSchemaDescription
idpathYesany—

Responses

200Workflow definition reset to code version
Content-Type: application/json
{
  "data": {
    "id": "code:checkout-flow",
    "workflowId": "checkout-flow",
    "workflowName": "Checkout Flow",
    "description": "Code-defined checkout workflow",
    "version": 1,
    "source": "code",
    "isCodeBased": true
  },
  "message": "Workflow definition reset to code version"
}
400Definition is not a code-based override
Content-Type: application/json
{
  "error": "This workflow definition is not a code-based override and cannot be reset"
}
404Workflow definition not found
Content-Type: application/json
{
  "error": "Workflow definition not found"
}
409Cannot reset - active workflow instances exist
Content-Type: application/json
{
  "error": "Cannot reset workflow definition with 3 active instance(s)"
}

Example

curl -X POST "http://108.165.128.56:3000/api/workflows/definitions/00000000-0000-4000-8000-000000000000/reset-to-code" \
  -H "Accept: application/json"
POST/workflows/definitions/{id}/test-step

Dry-run one activity config with mock-first semantics

Interpolates the supplied activity config against the sample context (plus a synthetic workflow scope and the server env allowlist) and runs the activity type's would-do mock. Never executes the real activity. Activity types that declare no mock or opt out with "refuse" respond 200 with a structured refusal the editor renders.

Parameters

NameInRequiredSchemaDescription
idpathYesanyUUID for DB definitions, or "code:<workflowId>" for code-based definitions

Request body (application/json)

{
  "stepId": "notify",
  "activityType": "SEND_EMAIL",
  "config": {
    "to": "{{context.customerEmail}}",
    "subject": "Order {{context.orderId}} approved"
  },
  "context": {
    "customerEmail": "jane@example.com",
    "orderId": "ORD-42"
  }
}

Responses

200Simulated mock output, or a structured refusal when the type cannot be simulated
Content-Type: application/json
{
  "simulated": true,
  "activityType": "SEND_EMAIL",
  "output": {
    "sent": false,
    "simulated": true,
    "wouldSendTo": "jane@example.com",
    "subject": "Order ORD-42 approved"
  },
  "interpolatedConfig": {
    "to": "jane@example.com",
    "subject": "Order ORD-42 approved"
  }
}
400Missing tenant context or malformed payload
Content-Type: application/json
{
  "error": "string"
}
403Insufficient permissions
Content-Type: application/json
{
  "error": "string"
}
404Workflow definition or activity type not found
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/workflows/definitions/string/test-step" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"activityType\": \"string\",
  \"config\": {}
}"
POST/workflows/definitions/generate

Author a draft workflow definition from natural language

Runs the propose-only workflows.workflow_author agent against this installation's activity, command, function and event catalogs and returns a draft definition plus the Problems-panel evaluation for it. Persists nothing: the draft is returned to the Studio for a human to apply, save and enable. Refusals ("unavailable" when no AI provider or agent registry is present, "failed" when the model call errored, "malformedResponse"/"schemaError" when the output is not a workflow definition) respond 200 with a structured body.

Request body (application/json)

{
  "prompt": "string"
}

Responses

200The generated draft with its Problems-panel evaluation, or a structured refusal
Content-Type: application/json
{
  "ok": true
}
400Invalid request body
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
403Insufficient permissions
Content-Type: application/json
{
  "error": "string"
}
500Generation failed unexpectedly
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X POST "http://108.165.128.56:3000/api/workflows/definitions/generate" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"prompt\": \"string\"
}"
GET/workflows/endpoints

List endpoints available to CALL_API activities

Returns a trimmed projection of the OpenAPI surface (path, method, summary, tag, parameters, and declared request/response schemas) consumed by the CALL_API endpoint picker. Endpoints outside this catalog can still be authored as free text. Responses without a declared schema omit responseSchema so consumers degrade to unknown typing.

Responses

200Endpoint catalog projected from the OpenAPI surface
Content-Type: application/json
{
  "items": [
    {
      "path": "string",
      "method": "string",
      "summary": "string",
      "tag": "string",
      "params": [
        {
          "name": "string",
          "in": "path",
          "required": true,
          "type": "string"
        }
      ],
      "hasRequestSchema": true
    }
  ]
}
400Missing tenant context
Content-Type: application/json
{
  "error": "string"
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
403Insufficient permissions
Content-Type: application/json
{
  "error": "string"
}
500Internal server error
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/workflows/endpoints" \
  -H "Accept: application/json"
GET/workflows/events

List all workflow events

Get a paginated list of all workflow events with filtering options

Parameters

NameInRequiredSchemaDescription
pagequeryNoany—
pageSizequeryNoany—
eventTypequeryNoany—
workflowInstanceIdqueryNoany—
userIdqueryNoany—
occurredAtFromqueryNoany—
occurredAtToqueryNoany—
sortFieldqueryNoany—
sortDirqueryNoany—

Responses

200List of workflow events
Content-Type: application/json
{
  "items": [
    {
      "id": "string",
      "workflowInstanceId": "00000000-0000-4000-8000-000000000000",
      "stepInstanceId": null,
      "eventType": "string",
      "occurredAt": "string",
      "userId": null,
      "workflowInstance": null
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
401Unauthorized
Content-Type: application/json
{
  "error": "string"
}
403Insufficient permissions
Content-Type: application/json
{
  "error": "string"
}
500Internal server error
Content-Type: application/json
{
  "error": "string"
}

Example

curl -X GET "http://108.165.128.56:3000/api/workflows/events?page=1&pageSize=50&sortField=occurredAt&sortDir=desc" \
  -H "Accept: application/json"