Organization-wide setup: profile, branding, directory, AI model selections and prompts, plus the channels and connectors that wire Cortex into the rest of the stack.
Common responses
These responses apply across endpoints in this section unless an endpoint documents an additional response.
Status
Meaning
Body
200
Request succeeded.
Endpoint response object.
201
Resource created.
Created resource object.
400
Invalid request.
Error envelope.
401
Missing or invalid bearer token.
Error envelope.
404
Resource not found or not visible to the current organization.
Error envelope.
Profile
Get organization profile
Get the current organization's profile. Returns the enriched `OrganizationRow` shape including live subscription plan details and user count.
Get the organization's branding profile. Returns color values, brand guidelines text, and presigned read URLs for each asset slot (`logo_light`, `logo_dark`, `brand_book`). A slot is `null` when no asset has been uploaded to it.
{
"branding": {
"organization_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"logo_light": {
"storage_key": "org-branding/a1b2c3d4-e5f6-7890-abcd-ef1234567890/logo_light/d4e5f6a7-b8c9-0123-defa-234567890123.png",
"filename": "acme-logo-light.png",
"mime_type": "image/png",
"size_bytes": 45312,
"get_url": "https://storage.example.com/org-branding/...?sig=..."
},
"logo_dark": null,
"brand_book": null,
"color_primary": "#1a2b3c",
"color_secondary": "#4d5e6f",
"color_accent": "#ff6600",
"guidelines_text": "Always use the primary color on white backgrounds.",
"updated_at": "2025-04-10T08:00:00.000Z"
}
}
Update branding
Update the organization's color palette and brand guidelines text. Pass an empty string for a color field to clear it. Asset slots (logos, brand book) are managed via the upload and confirm endpoints — they cannot be set here.
PATCH/v1/organization/branding
Request body
Name
Type
Required
Description
colorPrimary
string
Optional
Primary brand color as `#RRGGBB`. Pass `""` to clear.
colorSecondary
string
Optional
Secondary brand color as `#RRGGBB`. Pass `""` to clear.
colorAccent
string
Optional
Accent brand color as `#RRGGBB`. Pass `""` to clear.
guidelinesText
string
Optional
Plain-text brand guidelines. Max 8000 characters. Pass `""` to clear.
{
"branding": {
"organization_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"logo_light": {
"storage_key": "org-branding/a1b2c3d4-e5f6-7890-abcd-ef1234567890/logo_light/d4e5f6a7-b8c9-0123-defa-234567890123.png",
"filename": "acme-logo-light.png",
"mime_type": "image/png",
"size_bytes": 45312,
"get_url": "https://storage.example.com/org-branding/...?sig=..."
},
"logo_dark": null,
"brand_book": null,
"color_primary": "#1a2b3c",
"color_secondary": "#4d5e6f",
"color_accent": "#ff6600",
"guidelines_text": "Always use the primary color on white backgrounds.",
"updated_at": "2025-05-21T11:05:00.000Z"
}
}
Request branding upload URL
Request a presigned PUT URL to upload a branding asset directly to blob storage. After uploading to `uploadUrl`, call `PUT /organization/branding/assets/:slot` with the returned `storageKey` to confirm the asset. The URL expires in 300 seconds.
POST/v1/organization/branding/uploads
Request body
Name
Type
Required
Description
slot
string
Required
Asset slot to upload to. One of `"logo_light"`, `"logo_dark"`, or `"brand_book"`.
mimeType
string
Required
MIME type of the file being uploaded. Logos accept `image/png`, `image/svg+xml`, `image/jpeg`, `image/webp` (max 5 MB). Brand books accept `application/pdf` (max 25 MB).
sizeBytes
number
Required
Exact byte size of the file. Used to enforce per-slot size limits before issuing the upload URL.
Confirm a branding asset after uploading the file to the presigned URL. The `storageKey` must match the key returned by `POST /organization/branding/uploads` for this org and slot. Returns the full updated branding profile.
PUT/v1/organization/branding/assets/:slot
Path parameters
Name
Type
Required
Description
slot
string
Required
Asset slot being confirmed. One of `logo_light`, `logo_dark`, or `brand_book`.
Request body
Name
Type
Required
Description
storageKey
string
Required
The `storageKey` returned by the upload request. Max 1000 characters.
filename
string
Required
Original filename (plain basename, no path separators). Max 255 characters.
mimeType
string
Required
MIME type of the uploaded file. Must match the slot's allowed types.
List all departments in the organization, ordered by name. The `parentDepartmentId` field enables a tree structure — `null` denotes a top-level department.
Create a new department. Optionally nest it under a parent department by providing `parentDepartmentId`. Returns 400 if the specified parent does not exist in this organization.
POST/v1/organization/departments
Request body
Name
Type
Required
Description
name
string
Required
Department name. 1–200 characters.
description
string
Optional
Optional description. Max 2000 characters.
parentDepartmentId
string
Optional
UUID of the parent department for nesting. Pass `null` for a top-level department.
List the organization's data-leakage-protection content rules. Rules are regular expressions evaluated against every user message BEFORE it is stored or dispatched to a model: a matching active `allow` rule is an exception that always permits; otherwise a matching active `deny` rule blocks the message (the create-message endpoint returns 422 with code `dlp_blocked`).
Create a content rule. `pattern` (max 300 chars) must compile as a JavaScript regular expression — invalid patterns are rejected with 400, never stored. `action` is `deny` (block matching messages) or `allow` (exception that always permits). Rules default to active.
POST/v1/organization/dlp-rules
Request body
Name
Type
Required
Description
name
string
Required
Display name, max 100 characters.
pattern
string
Required
Regular expression, max 300 characters. Matched case-insensitively.
action
string
Required
`deny` or `allow`.
is_active
boolean
Optional
Defaults to true; inactive rules are not enforced.
Every platform feature flag resolved for the caller's organization — an org override shadows the platform default, and a flag with no row resolves `false`. Read-only: toggling is a platform-operator action in the console. Clients read this once per session to drive flag-gated UI (run progress presentation, intermediary file visibility).
List the organization's custom themes. Built-in themes (`cortex`, `solid-slate`) are code-defined and never appear here. Each theme carries a `palette_id` (`custom-<id>`) — the value used in `allowed_themes`, `default_theme`, and the `data-theme` attribute.
Create a custom theme. Token maps are flat objects of CSS custom property name (`--kebab-case`, max 64 chars) to value. Values are strictly validated — `{ } ; @`, `url(`, and comment/tag sequences are rejected — because they compile verbatim into the public stylesheet. At least one variant (light or dark) must stay enabled.
POST/v1/organization/themes
Request body
Name
Type
Required
Description
name
string
Required
Display name, 1–80 characters.
surface
string
Optional
`glass` or `flat`. Default `glass`.
light_enabled
boolean
Optional
Whether the light variant is available. Default `true`.
dark_enabled
boolean
Optional
Whether the dark variant is available. Default `true`.
light_tokens
object
Optional
CSS custom properties for the light variant.
dark_tokens
object
Optional
CSS custom properties for the dark variant.
brand_inputs
object
Optional
What the theme studio's composer held: `{ brief, attachments: [{ kind: "site" | "book", label, url?, detail?, brand_name?, colors, neutrals, guidelines? }] }`. A brand book is stored as its extraction (name, size, colours, excerpt), never the PDF. Restored when the theme is reopened; `null` to clear.
Delete a custom theme. The theme is also scrubbed from the organization's `allowed_themes` (falling back to the built-ins when the list would become empty) and cleared as `default_theme` if it was the default. Returns `204 No Content`.
Compiled CSS for a custom theme. Public by design — stylesheet `<link>` tags cannot carry credentials; the unguessable uuid is the capability, and the response contains only design-token values. Supports `ETag`/`If-None-Match` revalidation and omits disabled variants.
Request a presigned upload for a per-variant backdrop photo. Returns `upload_url` (PUT the file there with `x-ms-blob-type: BlockBlob`) and `asset_id`. Allowed types: png, jpeg, webp, avif; max 8 MB.
Attach an uploaded asset as the variant's backdrop. Fails if the blob was never uploaded. Replacing a backdrop deletes the previous blob; the compiled stylesheet gains `--app-backdrop: url(...)` for that variant.
Ask the organization's base model for a coordinated light + dark palette. Any combination of a free-text brief, the brand's name, anchor colors (from a brand book, a website, or the theme being refined) and an excerpt of written guidelines can be sent; at least one of `brief` (3+ characters), `colors` or `guidelines` (20+ characters) is required. The model only proposes the design intent: `--primary`, the page, card, popover and sidebar surfaces, the body text and the four status hues. With `scope: "full"` the API derives everything else deterministically on top — hover, muted and secondary fills, borders and rings as low-chroma steps off their own surface, every text-on-fill colour by WCAG contrast, brand and status colours nudged until they read on their surface, plus gradients, glass tints and chrome — so a brand colour can never land in a hover fill and the result always passes stylesheet validation.
POST/v1/organization/themes/suggest-colors
Request body
Name
Type
Required
Description
brief
string
Optional
Free-text direction, up to 2000 characters, e.g. `"warmer, less contrast in dark mode"`.
brand_name
string
Optional
The brand the theme is for, up to 120 characters.
colors
string[]
Optional
Up to 12 anchor colors as `#rrggbb`. The most prominent saturated one becomes `--primary`.
guidelines
string
Optional
Written brand guidance for the model, up to 8000 characters (typically the `excerpt` from the brand-book endpoint).
scope
string
Optional
`"colors"` (default) returns the intent tokens the model chose; `"full"` expands them into a complete, contrast-checked theme.
surface
string
Optional
`"glass"` (default) or `"flat"`. Used by `scope: "full"` to derive the matching chrome.
The theme engine behind generation, exposed for editors; pure and fast, no model call. Send a theme's token maps and get back two things. First, when `changed` names the Palette swatch that was just edited, the tokens that follow it for that variant — text on primary, the focus ring and the sidebar's active colour for a new brand colour; hover, muted and secondary fills, borders and panels for a new page colour; the whole sidebar family for a new rail colour — re-derived from the theme's core palette. Second, for each variant, the readability checks: text/surface pairs under 4.5:1, emphasis colours under 3:1 on their surface, structural fills that look like a brand colour or sit far from their surface, and panels far from the page. Each issue carries a `fix` map holding the values generation would have produced.
POST/v1/organization/themes/derive
Request body
Name
Type
Required
Description
surface
string
Required
`"glass"` or `"flat"`.
light_tokens
object
Optional
The light variant's tokens, name → value. Omit a variant to skip it.
dark_tokens
object
Optional
The dark variant's tokens.
changed
object
Optional
Optional `{ variant, token, previous? }`: the Palette swatch just edited (`--primary`, `--background`, `--foreground`, `--sidebar-background` or `--accent-gradient`) and its value before the edit. With `--primary`, `previous` lets the action gradient follow while it is still the derived one.
`{ light_tokens, dark_tokens, light_issues, dark_issues }` — the dependent tokens for the changed variant (empty without `changed`) and `{ code, message, tokens, fix }` issues per variant
400
Malformed body, or a token map that fails stylesheet validation
Fetch a public web page (plus a few of its same-origin stylesheets) and mine its most brand-looking colors — the page's `theme-color` meta always leads. Only public http(s) hosts are allowed (SSRF-guarded); responses are size- and time-capped. Returns `host`, ranked `colors` (hex), and `theme_color`.
Read a brand-guidelines PDF and return what the theme studio needs to generate a theme from it: the colors the document names (hex, `rgb()`, RGB/CMYK listings and `HEX` labels are all recognised), a title, and a short excerpt of the text for the model. Only the first 80 pages are read. The file is processed in memory and never stored.
Send `multipart/form-data` with the PDF in the `file` field (up to 20 MB). Scanned PDFs without a text layer return 422.
POST/v1/organization/themes/extract-brand-book
Request body
Name
Type
Required
Description
file
file
Required
The brand book as a PDF, up to 20 MB. Multipart field name `file`.
{
"filename": "acme-brand-guidelines.pdf",
"page_count": 24,
"title": "Acme Robotics — Brand guidelines",
"colors": [
"#0e7c66",
"#f4b942",
"#0b3b2e"
],
"neutrals": [
"#f5f3ee",
"#2b2b2b"
],
"excerpt": "Our primary green #0E7C66 carries every action. Amber #F4B942 is reserved for highlights…"
}
Generate background (AI)
Generate a backdrop photo from a prompt using the organization's image model (OpenAI-backed models currently), store it as the variant's background asset, and return the updated theme. Replaces (and deletes) any previous backdrop for that variant.
Streams a theme background image. Public by design — CSS `url()` cannot carry credentials; the unguessable asset uuid is the capability. Asset ids are immutable, so responses cache long (`max-age=86400, immutable`).
The organization's theme policy: which themes members may pick (`allowed_themes`) and which one seeds members who never picked (`default_theme`, `null` = platform default). Ids are built-in slugs or `custom-<uuid>` values.
Replace the theme policy. Every id must be a built-in or one of the organization's custom themes, and `defaultTheme` (when non-null) must be in `allowedThemes`.
PUT/v1/organization/appearance
Request body
Name
Type
Required
Description
defaultTheme
string | null
Required
Theme id that seeds members without a preference, or `null`.
Get the full AI model catalog. Returns all configured providers grouped with their models (families), each with the versions an organization may select, plus a reference ranking sourced from the Arena.ai leaderboard. A family's `display_name` is the model name; `versions` lists every **active** version of the family — active is what makes a version selectable, and each is offered on its own (`is_latest` marks the family's current `latest_version_id`). A version's `display_name` is the provider's own name for it (e.g. `Claude Opus 4.5`, or a readable form of the id when the provider publishes none) — the label to show when offering the choice. Inactive versions, inactive families and versions with no usable output are omitted. The `selectable` flag on a provider, family or version indicates whether the org can pin it via the model-selections endpoint: a provider is selectable when it has a runtime adapter in the worker AND has a stored API key configured. Providers without a runtime adapter (e.g. Google) are never selectable, and a provider with a runtime adapter but no stored key shows as unselectable until a key is added.
List the model version the organization has pinned for each activity. `version_id` and `version` are the exact version that runs (its `display_name` is the provider's own name for it); `family_id` and `family_name` name the model it belongs to. Selections made before versions could be pinned resolve to their model's latest version. Activities without an explicit selection are omitted.
Pin an exact model version for a specific activity; the worker runs that version until the selection changes. The activity must be one of the values returned by `get-model-catalog` (`base`, `assistant_text`, `thinking`, `voice`, `image`, `presentation`, `spreadsheet_analysis`, `title_generation`, `embedding`). The version must be active (active is what makes it selectable), belong to an active model of a selectable provider, and support the activity. Returns the updated selection with `version_id` and `version` (the pinned version, with the provider's `display_name` for it) and the `family_id`/`family_name` of the model it belongs to.
PUT/v1/organization/model-selections/:activity
Path parameters
Name
Type
Required
Description
activity
string
Required
Activity to configure. One of `base`, `assistant_text`, `thinking`, `voice`, `image`, `presentation`, `spreadsheet_analysis`.
Request body
Name
Type
Required
Description
versionId
string
Required
UUID of the model version to pin for this activity — one of the `versions[].id` values from `get-model-catalog`.
enabled
boolean
Optional
Whether this selection is active. Defaults to `true`.
`VersionNotFound`, `ProviderNotConfigured` (no runtime adapter or stored key), `VersionNotActive` (version or its model inactive), or `VersionDoesNotSupportActivity`.
List every system prompt configured at any scope level (company or department). Each item includes a `scope` discriminator describing where the prompt applies.
{
"data": [
{
"scope": {
"type": "company"
},
"prompt_text": "You are a helpful assistant for Acme Corp. Always respond professionally and concisely.",
"updated_at": "2026-03-10T09:00:00.000Z"
},
{
"scope": {
"type": "department",
"id": "dept-0001-4000-a000-000000000001"
},
"prompt_text": "You assist the Sales team. Prioritize lead qualification and pipeline updates.",
"updated_at": "2026-04-01T11:30:00.000Z"
}
],
"has_more": false,
"next_cursor": null
}
Upsert company prompt
Set or replace the company-wide system prompt. Passing an empty string for `promptText` deletes the prompt and returns 204. Otherwise returns the saved prompt.
PUT/v1/organization/system-prompts/company
Request body
Name
Type
Required
Description
promptText
string
Required
Prompt text. Max 8000 characters. Pass an empty string to delete the company prompt.
Set or replace a per-department system prompt override. Passing an empty string for `promptText` deletes the override and returns 204. Otherwise returns the saved prompt.
List outbound connectors configured for the organization. Pass `?type=m365` to filter to a single connector type. Secrets are never returned — only public-safe fields are included in each object.
GET/v1/organization/integrations
Query parameters
Name
Type
Required
Description
type
string
Optional
Filter by integration type. Currently supported connector types: `m365`.
Connect a new outbound integration. The `config` and `secrets` fields are validated and probed against the external service before the record is saved. Secrets are encrypted at rest and never returned in responses. Returns 201 on success.
POST/v1/organization/integrations
Request body
Name
Type
Required
Description
type
string
Required
Integration type. One of: `m365`.
displayName
string
Required
Human-readable label for this connector (1–200 characters).
config
object
Required
Kind-specific non-secret configuration. For `m365`: `{ tenantId, clientId }`.
secrets
object
Required
Kind-specific secrets. For `m365`: `{ clientSecret }`. Encrypted at rest; never echoed back.
Update a connector's display name, config, or secrets. All fields are optional; only provided fields are changed. If `config` or `secrets` change, the integration is re-validated and re-probed before saving.
PATCH/v1/organization/integrations/:integrationId
Path parameters
Name
Type
Required
Description
integrationId
string
Required
The integrationId value from the endpoint path.
Request body
Name
Type
Required
Description
displayName
string
Optional
New display name (1–200 characters).
config
object
Optional
Partial config update. Merged with existing config.
secrets
object
Optional
Partial secrets update. Merged with existing secrets, re-encrypted.
Re-validate and re-probe a connector's stored credentials against the external service. On success the integration's `status` is set to `connected` and `lastValidatedAt` is refreshed. On probe failure the `status` is set to `error` and `lastError` is populated — the updated record is returned either way.
List outbound connectors configured for the caller's organization. Connectors are external services Cortex calls on the org's behalf (e.g. Microsoft 365). Only `id`, `type`, `displayName`, `status`, `lastValidatedAt`, and timestamps are returned — secrets and operator-only config are excluded. Full management lives under Organizations > Integrations.
List inbound channels configured for the organization. Pass `?type=telegram` to filter to a single channel type. Secrets are never returned — only public-safe fields are included in each object.
GET/v1/organization/integrations
Query parameters
Name
Type
Required
Description
type
string
Optional
Filter by integration type. Currently supported channel types: `telegram`.
Connect a new inbound channel. The bot token (secret) is validated against Telegram's `getMe` API before the record is saved. On success the `botUsername` is stored in `config`. Secrets are encrypted at rest and never returned. Returns 201 on success.
POST/v1/organization/integrations
Request body
Name
Type
Required
Description
type
string
Required
Integration type. One of: `telegram`.
displayName
string
Required
Human-readable label for this channel (1–200 characters).
config
object
Required
Kind-specific non-secret configuration. For `telegram`: `{}` (Telegram has no non-secret config fields at creation time; `botUsername` is populated automatically from the probe).
secrets
object
Required
Kind-specific secrets. For `telegram`: `{ botToken }`. Encrypted at rest; never echoed back.
Update a channel's display name, config, or bot token. All fields are optional; only provided fields are changed. If `secrets` changes, the new bot token is validated against Telegram before saving.
PATCH/v1/organization/integrations/:integrationId
Path parameters
Name
Type
Required
Description
integrationId
string
Required
The integrationId value from the endpoint path.
Request body
Name
Type
Required
Description
displayName
string
Optional
New display name (1–200 characters).
config
object
Optional
Partial config update. Merged with existing config.
secrets
object
Optional
Partial secrets update. For `telegram`: `{ botToken }`. Merged with existing secrets, re-encrypted.
Re-validate and re-probe a channel's stored bot token against Telegram's `getMe` API. On success the `status` is set to `connected`, `lastValidatedAt` is refreshed, and `config.botUsername` is updated if the bot username changed. On probe failure the `status` is set to `error` and `lastError` is populated — the updated record is returned either way.
List inbound channels configured for the caller's organization. Channels are surfaces through which end users reach Cortex (e.g. Telegram). Only `id`, `type`, `displayName`, `status`, `lastValidatedAt`, and timestamps are returned — secrets and operator-only config are excluded. Full management lives under Organizations > Integrations.