openapi: 3.0.0
info:
title: PipesHub API
description: |
Unified API documentation for PipesHub services.
PipesHub is an enterprise-grade platform providing:
- User authentication and management
- Document storage and version control
- Knowledge base management
- Enterprise search and conversational AI
- Third-party integrations via connectors
- System configuration management
- Crawling job scheduling
- Email services
## Authentication
Most endpoints require JWT Bearer token authentication. Some internal endpoints use scoped tokens for service-to-service communication.
**OAuth 2.0 Bearer tokens** from `POST /oauth2/token` use the same `Authorization: Bearer` header. For **`client_credentials`**, machine tokens may encode `userId === client_id` in the JWT; the **Node API gateway** resolves the OAuth **app creator** and sets the authenticated user accordingly. See the **OAuth Provider** tag for full behavior.
## Base URLs
All endpoints use the `/api/v1` prefix unless otherwise noted.
version: 1.0.0
contact:
name: API Support
email: support@pipeshub.com
servers:
- url: '{instance_url}/api/v1'
description: Base API URL
variables:
instance_url:
default: https://app.pipeshub.com
description: Base server URL (without /api/v1)
- url: '{instance_url}'
description: Root URL (used for MCP endpoints mounted at /mcp)
variables:
instance_url:
default: https://app.pipeshub.com
description: Base server URL
tags:
- name: User Account
description: User authentication including multi-step MFA, password reset, OTP login, and token management
- name: Organization Auth Config
description: Admin configuration of authentication methods including MFA steps and allowed providers
- name: OAuth Provider
description: |
PipesHub OAuth 2.0 Authorization Server implementing RFC 6749, RFC 7636 (PKCE), and OpenID Connect.
**Supported Grant Types:**
- `authorization_code` - Standard OAuth flow with PKCE support
- `client_credentials` - Machine-to-machine authentication
- `refresh_token` - Token refresh for long-lived access
**Security Features:**
- PKCE (Proof Key for Code Exchange) for public clients
- State parameter for CSRF protection
- Configurable token lifetimes
- Token revocation and introspection
**OpenID Connect:**
- ID tokens with standard claims
- UserInfo endpoint for profile data
- Discovery endpoint for automatic configuration
**Machine tokens (`client_credentials`) — gateway and downstream identity:**
Access tokens may encode **`userId === client_id`**. The **Node.js API gateway** resolves the effective user to the OAuth **app creator**: first using the JWT **`createdBy`** claim when present, otherwise by loading the OAuth app by **`client_id`** from the registry. After verification it sets the authenticated session to that creator.
**Python services:** Validate `Authorization: Bearer` as today and use the JWT payload’s **`userId`** as-is for scopes and user-scoped logic (which may still equal **`client_id`** for machine tokens).
**Operational note:** Prefer tokens whose JWT already carries the creator as **`userId`**; use **`POST /oauth-clients/{appId}/revoke-all-tokens`** and obtain new tokens from **`POST /oauth2/token`** when rotating integrations.
- name: OAuth Apps
description: |
Manage OAuth 2.0 client applications registered with PipesHub.
OAuth apps allow third-party applications to access PipesHub APIs on behalf of users
or organizations. Each app receives a client ID and secret for authentication.
**Who can see which apps**
- **Everyone (including org admins)** sees and manages only OAuth apps **they created** (`createdBy`). Other members' apps are hidden (not listed; individual operations return not found).
**Who authorizes vs. client credentials**
- **Authorization code:** Any authenticated user in the workspace may complete consent for a valid `client_id`; issued tokens represent **that user**.
- **Client credentials:** Access tokens represent the **OAuth app creator** (who registered the client), not the caller.
**Scopes**
- `GET /oauth-clients/scopes` returns scopes grouped by category for the **signed-in user's role**.
- **Org admins** may register apps that request additional **admin-only** scopes; non-admins cannot select those scopes when creating or updating an app.
**App Types:**
- **Confidential clients**: Server-side apps that can securely store secrets
- **Public clients**: Browser/mobile apps that cannot securely store secrets (use PKCE)
**App Lifecycle:**
- Create apps with name, redirect URIs, allowed scopes, and optional URLs (homepage, privacy, terms)
- Regenerate secrets if compromised
- Suspend/activate apps to control access
- Revoke all tokens for emergency access removal
- name: OpenID Connect
description: |
OpenID Connect 1.0 endpoints for identity federation and discovery.
**Discovery:**
- `/.well-known/openid-configuration` - Authorization server metadata
- `/.well-known/oauth-authorization-server` - Authorization server metadata (RFC 8414)
- `/.well-known/oauth-protected-resource/mcp` - Protected resource metadata (RFC 9728)
- `/.well-known/jwks.json` - Public keys for token verification
**UserInfo:**
- `/oauth2/userinfo` - Get authenticated user's profile information
**Supported Claims:**
- `user_id` - User identifier
- `email`, `email_verified` - Email information
- `name`, `given_name`, `family_name` - Name information
- name: Organizations
description: Organization management operations
- name: Knowledge Base
description: Knowledge base management operations
- name: Knowledge Hub
description: Unified browse API for root and child nodes (apps, record groups, folders, records) with filtering and search
- name: Conversations
description: AI-powered conversational chat management with citations and follow-up questions
- name: Semantic Search
description: Enterprise semantic search across all indexed knowledge with relevance scoring
- name: Agents
description: Custom AI agents with specialized capabilities and tool integrations
- name: AI Models Providers
description: Manage individual AI model providers - add, update, delete, and set defaults.
- name: Web Search
description: Manage web search providers (DuckDuckGo, Serper, Tavily, Exa) and settings for internet search.
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: JWT Bearer token for authenticated requests
scopedToken:
type: http
scheme: bearer
bearerFormat: JWT
description: |
Scoped JWT token for service-to-service authentication.
Format: "Bearer {scoped_token}"
Required scopes vary by endpoint.
oauth2:
type: oauth2
description: |
OAuth 2.0 authentication with fine-grained scopes.
Supports authorization_code (with PKCE) and client_credentials flows.
OAuth tokens are Bearer JWTs — use the same Authorization header as regular tokens.
For **client_credentials**, machine JWTs may use `userId === client_id`; the Node gateway resolves the OAuth app creator — see **OAuth Provider** tag.
flows:
authorizationCode:
authorizationUrl: /api/v1/oauth2/authorize
tokenUrl: /api/v1/oauth2/token
refreshUrl: /api/v1/oauth2/token
scopes:
openid: OpenID Connect authentication
profile: User profile information
email: User email address
offline_access: Offline access (refresh tokens)
org:read: Read organization information
org:write: Update organization settings
org:admin: Full organization administration
user:read: Read user profiles
user:write: Update user profiles
user:invite: Invite new users
user:delete: Delete users
usergroup:read: Read user groups
usergroup:write: Create and manage user groups
team:read: Read team information
team:write: Create and manage teams
kb:read: Read knowledge bases and records
kb:write: Create and update knowledge bases
kb:delete: Delete knowledge bases and records
kb:upload: Upload files to knowledge bases
semantic:read: Read semantic search results and history
semantic:write: Execute semantic search
semantic:delete: Delete semantic search history
conversation:read: Read conversations
conversation:write: Create and manage conversations
conversation:chat: Send messages in conversations
agent:read: Read AI agents
agent:write: Create and manage AI agents
agent:execute: Execute AI agents
connector:read: Read connector configurations
connector:write: Create and update connectors
connector:sync: Trigger connector synchronization
connector:delete: Delete connectors
config:read: Read system configuration
config:write: Update system configuration
crawl:read: Read crawling jobs
crawl:write: Create and manage crawling jobs
crawl:delete: Delete crawling jobs
clientCredentials:
tokenUrl: /api/v1/oauth2/token
scopes:
openid: OpenID Connect authentication
profile: User profile information
email: User email address
offline_access: Offline access (refresh tokens)
org:read: Read organization information
org:write: Update organization settings
org:admin: Full organization administration
user:read: Read user profiles
user:write: Update user profiles
user:invite: Invite new users
user:delete: Delete users
usergroup:read: Read user groups
usergroup:write: Create and manage user groups
team:read: Read team information
team:write: Create and manage teams
kb:read: Read knowledge bases and records
kb:write: Create and update knowledge bases
kb:delete: Delete knowledge bases and records
kb:upload: Upload files to knowledge bases
semantic:write: Execute semantic search
semantic:read: Read semantic search results and history
semantic:delete: Delete semantic search history
conversation:read: Read conversations
conversation:write: Create and manage conversations
conversation:chat: Send messages in conversations
agent:read: Read AI agents
agent:write: Create and manage AI agents
agent:execute: Execute AI agents
connector:read: Read connector configurations
connector:write: Create and update connectors
connector:sync: Trigger connector synchronization
connector:delete: Delete connectors
config:read: Read system configuration
config:write: Update system configuration
crawl:read: Read crawling jobs
crawl:write: Create and manage crawling jobs
schemas:
AuthMethod:
type: object
additionalProperties: false
description: Authentication method configuration
properties:
type:
type: string
enum:
- samlSso
- otp
- password
- google
- microsoft
- azureAd
- oauth
description: |
Type of authentication method:
- `password`: Email/password authentication
- `otp`: One-time password via email (6-digit, expires in 10 minutes)
- `google`: Google OAuth 2.0
- `microsoft`: Microsoft OAuth 2.0
- `azureAd`: Azure Active Directory
- `samlSso`: SAML 2.0 Single Sign-On
- `oauth`: Generic OAuth 2.0 provider
required:
- type
AuthStep:
type: object
additionalProperties: false
description: A single step in multi-factor authentication flow
properties:
order:
type: integer
description: Order of the authentication step (1-3, must be unique across steps)
minimum: 1
maximum: 3
allowedMethods:
type: array
items:
$ref: '#/components/schemas/AuthMethod'
description: List of allowed authentication methods for this step. User can choose any one method from this list.
minItems: 1
required:
- order
- allowedMethods
AuthConfig:
type: object
additionalProperties: false
description: |
Organization authentication configuration. Supports 1-3 authentication steps for multi-factor authentication.
**Validation Rules:**
- Minimum 1 step, maximum 3 steps
- Each step must have unique order
- No duplicate methods within the same step
- No method can appear in multiple steps
properties:
authMethods:
type: array
items:
$ref: '#/components/schemas/AuthStep'
description: List of authentication steps in order
minItems: 1
maxItems: 3
required:
- authMethods
UpdateAuthMethodResponse:
type: object
additionalProperties: false
description: Response after updating organization authentication methods
properties:
message:
type: string
example: Auth method updated
authMethod:
type: array
description: Updated authentication steps (same shape as request body)
items:
$ref: '#/components/schemas/AuthStep'
required:
- message
- authMethod
OrgAuthConfigSetupResponse:
type: object
additionalProperties: false
description: Response from setting up organization auth configuration
properties:
message:
type: string
required:
- message
InitAuthRequest:
type: object
additionalProperties: false
description: |
Optional JSON body for `/userAccount/initAuth`. Valid shapes include: omitting the body entirely, sending `{}` (empty object), or `{ "email": "
" }`. Neither the body nor `email` is required. When `email` is omitted or empty, the session is still created and `allowedMethods` / `authProviders` are returned as usual; clients typically supply `email` later on `/userAccount/authenticate`. The `email` property remains supported mainly for legacy clients and backward compatibility.
properties:
email:
type: string
format: email
description: |
Optional; retained for legacy reasons. When set, stored on the auth session for correlation with later `/authenticate` calls (RFC 5321 compliant address).
example: user@example.com
InitAuthResponse:
type: object
additionalProperties: false
description: Response containing available authentication methods and session info
properties:
currentStep:
type: integer
description: Current authentication step (0-indexed). Always 0 for initial response.
example: 0
allowedMethods:
type: array
items:
type: string
enum:
- samlSso
- otp
- password
- google
- microsoft
- azureAd
- oauth
description: List of allowed authentication methods for the current step
example:
- password
- google
- otp
message:
type: string
description: Response message
example: Authentication initialized
authProviders:
$ref: '#/components/schemas/AuthProviders'
jitEnabled:
type: boolean
description: True when at least one allowed external provider has JIT provisioning enabled
required:
- currentStep
- allowedMethods
- message
- authProviders
- jitEnabled
AuthProviderGooglePublicConfig:
type: object
additionalProperties: false
description: Public Google OAuth settings returned to clients
properties:
clientId:
type: string
description: Google OAuth client ID
enableJit:
type: boolean
description: Whether just-in-time user provisioning is enabled for Google
AuthProviderMicrosoftPublicConfig:
type: object
additionalProperties: false
description: Public Microsoft OAuth settings returned to clients
properties:
tenantId:
type: string
description: Microsoft tenant ID
clientId:
type: string
description: Microsoft OAuth client ID
enableJit:
type: boolean
description: Whether just-in-time user provisioning is enabled for Microsoft
AuthProviderAzureAdPublicConfig:
type: object
additionalProperties: false
description: Public Azure AD OAuth settings returned to clients
properties:
tenantId:
type: string
description: Azure AD tenant ID
clientId:
type: string
description: Azure AD client ID
enableJit:
type: boolean
description: Whether just-in-time user provisioning is enabled for Azure AD
AuthProviderOAuthPublicConfig:
type: object
additionalProperties: false
description: Public generic OAuth provider settings returned to clients
properties:
providerName:
type: string
description: Custom OAuth provider display name
clientId:
type: string
description: OAuth client ID
tokenEndpoint:
type: string
description: OAuth token endpoint URL
authorizationUrl:
type: string
description: OAuth authorization URL
clientSecret:
type: string
description: Client secret (omitted when stripped for public responses)
userInfoEndpoint:
type: string
description: UserInfo endpoint URL
scope:
type: string
description: Default OAuth scopes
enableJit:
type: boolean
description: Whether just-in-time user provisioning is enabled for this provider
required:
- providerName
- clientId
- tokenEndpoint
- authorizationUrl
AuthProviders:
type: object
additionalProperties: false
description: Configuration for external authentication providers (returned when those methods are allowed)
properties:
google:
$ref: '#/components/schemas/AuthProviderGooglePublicConfig'
microsoft:
$ref: '#/components/schemas/AuthProviderMicrosoftPublicConfig'
azuread:
$ref: '#/components/schemas/AuthProviderAzureAdPublicConfig'
oauth:
$ref: '#/components/schemas/AuthProviderOAuthPublicConfig'
saml:
type: object
description: Present when SAML SSO is an allowed method; may be an empty object
additionalProperties: true
AuthenticateRequest:
type: object
additionalProperties: false
description: |
Request to authenticate using specified method.
**Credential format varies by method:**
- `password`: `{ password: "string" }`
- `otp`: `{ otp: "123456" }` (6-digit code)
- `google`: `"google-id-token-string"`
- `microsoft`: `{ accessToken: "...", idToken: "..." }`
- `azureAd`: `{ accessToken: "...", idToken: "..." }`
- `oauth`: `{ accessToken: "...", idToken: "..." }`
- `samlSso`: handled via redirect flow
properties:
method:
type: string
enum:
- samlSso
- otp
- password
- google
- microsoft
- azureAd
- oauth
description: Authentication method to use
credentials:
oneOf:
- $ref: '#/components/schemas/PasswordCredentials'
- $ref: '#/components/schemas/OtpCredentials'
- $ref: '#/components/schemas/OAuthCredentials'
- type: string
description: Google ID token (for google method)
description: Credentials based on the authentication method
email:
type: string
format: email
description: Optional email for verification (used with some OAuth methods)
cf-turnstile-response:
type: string
description: Cloudflare Turnstile CAPTCHA token (optional, if CAPTCHA is enabled)
required:
- method
- credentials
PasswordCredentials:
type: object
additionalProperties: false
description: Credentials for password authentication
properties:
password:
type: string
description: User password
format: password
required:
- password
OtpCredentials:
type: object
additionalProperties: false
description: Credentials for OTP authentication
properties:
otp:
type: string
description: 6-digit one-time password
pattern: ^\d{6}$
example: '123456'
required:
- otp
OAuthCredentials:
type: object
additionalProperties: false
description: Credentials for OAuth authentication (Microsoft, Azure AD, generic OAuth)
properties:
accessToken:
type: string
description: OAuth access token
idToken:
type: string
description: OAuth ID token (JWT)
required:
- accessToken
AuthenticateMultiStepResponse:
type: object
additionalProperties: false
description: Current authentication step succeeded; additional MFA steps remain
properties:
status:
type: string
enum:
- success
description: Step completion status
nextStep:
type: integer
description: Next authentication step index
allowedMethods:
type: array
items:
type: string
description: Allowed method types for the next step
authProviders:
$ref: '#/components/schemas/AuthProviders'
required:
- status
- nextStep
- allowedMethods
- authProviders
AuthenticateFinalResponse:
type: object
additionalProperties: false
description: All authentication steps complete; JWT tokens returned
properties:
message:
type: string
description: Success message
example: Fully authenticated
accessToken:
type: string
description: JWT access token (1 hour expiry)
refreshToken:
type: string
description: JWT refresh token (7 days expiry)
required:
- message
- accessToken
- refreshToken
AuthenticateResponse:
oneOf:
- $ref: '#/components/schemas/AuthenticateMultiStepResponse'
- $ref: '#/components/schemas/AuthenticateFinalResponse'
description: |
Either the next step in a multi-factor flow (`status`, `nextStep`, `allowedMethods`, `authProviders`)
or final tokens (`message`, `accessToken`, `refreshToken`).
AuthenticatedPasswordResetResponse:
type: object
additionalProperties: false
description: Response after authenticated user changes password (new access token issued)
properties:
data:
type: string
example: password reset
accessToken:
type: string
description: New JWT access token after password change
required:
- data
- accessToken
RefreshTokenResponse:
type: object
additionalProperties: false
description: Response with new access token
properties:
user:
$ref: '#/components/schemas/RefreshTokenUser'
accessToken:
type: string
description: New JWT access token (24 hour default expiry, configurable via ACCESS_TOKEN_EXPIRY)
required:
- user
- accessToken
RefreshTokenUser:
type: object
additionalProperties: false
description: User record returned with a refreshed access token
properties:
_id:
type: string
description: User ID
orgId:
type: string
description: Organization ID
email:
type: string
format: email
fullName:
type: string
firstName:
type: string
lastName:
type: string
designation:
type: string
hasLoggedIn:
type: boolean
isDeleted:
type: boolean
slug:
type: string
createdAt:
type: string
updatedAt:
type: string
__v:
type: integer
required:
- _id
- orgId
- email
- fullName
- hasLoggedIn
- isDeleted
- slug
- createdAt
- updatedAt
- __v
OrgAuthConfigCreateRequest:
type: object
additionalProperties: false
description: Request to create initial organization auth configuration
properties:
contactEmail:
type: string
format: email
description: Organization contact email
registeredName:
type: string
description: Organization registered name
adminFullName:
type: string
description: Admin user full name
sendEmail:
type: boolean
description: Whether to send welcome email
default: false
required:
- contactEmail
- registeredName
- adminFullName
ErrorResponse:
type: object
additionalProperties: false
description: |
Standard error envelope returned by all errors routed through `ErrorMiddleware`.
Applies to all `BaseError` subclasses including `HttpError`, `ValidationError`, and others.
The `code` field is a machine-readable string identifying the error type (e.g.
`HTTP_UNAUTHORIZED`, `HTTP_NOT_FOUND`, `VALIDATION_ERROR`, `INTERNAL_ERROR`).
properties:
error:
type: object
additionalProperties: false
required:
- code
- message
properties:
code:
type: string
description: |
Machine-readable error code. For application errors it takes the form `HTTP_`
For unhandled runtime errors (e.g. database unavailable) it is `INTERNAL_ERROR`.
example: HTTP_BAD_REQUEST
message:
type: string
description: Human-readable description of the error
example: Admin access required
metadata:
type: object
description: Additional context (only present in development environments)
additionalProperties: true
required:
- error
StreamRecordErrorResponse:
type: object
additionalProperties: false
description: |
Error payload returned by the legacy record-stream proxy when the downstream
streaming request fails after route middleware has passed.
required:
- error
properties:
error:
type: string
description: Human-readable error message from the gateway or downstream stream service
OAuthTokenRequest:
type: object
description: |
OAuth 2.0 Token Request (RFC 6749 Section 4.1.3).
Request body for exchanging authorization code or credentials for tokens.
properties:
grant_type:
type: string
enum:
- authorization_code
- client_credentials
- refresh_token
description: |
OAuth grant type:
- `authorization_code`: Exchange auth code for tokens
- `client_credentials`: Machine-to-machine auth
- `refresh_token`: Get new access token using refresh token
code:
type: string
description: Authorization code (required for authorization_code grant)
redirect_uri:
type: string
format: uri
description: Redirect URI (required for authorization_code grant)
client_id:
type: string
description: Client ID (can also be sent via Basic auth header)
client_secret:
type: string
description: Client secret (can also be sent via Basic auth header)
refresh_token:
type: string
description: Refresh token (required for refresh_token grant)
scope:
type: string
description: Requested scopes (optional, defaults to original grant scopes)
code_verifier:
type: string
description: |
PKCE code verifier (RFC 7636). Required if code_challenge was used.
Must be 43-128 characters from [A-Za-z0-9-._~]
pattern: ^[A-Za-z0-9\-._~]{43,128}$
required:
- grant_type
OAuthTokenResponse:
type: object
description: |
OAuth 2.0 Token Response (RFC 6749 Section 5.1).
Contains the access token and optional refresh/ID tokens.
properties:
access_token:
type: string
description: The access token for API requests
token_type:
type: string
example: Bearer
description: Token type (always "Bearer")
expires_in:
type: integer
description: Access token lifetime in seconds
example: 3600
refresh_token:
type: string
description: Refresh token for obtaining new access tokens
scope:
type: string
description: Granted scopes (may differ from requested)
id_token:
type: string
description: OpenID Connect ID token (JWT) if openid scope was requested
OAuthRevokeRequest:
type: object
description: |
OAuth 2.0 Token Revocation Request (RFC 7009).
Revokes an access or refresh token.
properties:
token:
type: string
description: The token to revoke
token_type_hint:
type: string
enum:
- access_token
- refresh_token
description: Hint about token type (optional, improves performance)
client_id:
type: string
description: Client ID
client_secret:
type: string
description: Client secret
required:
- token
- client_id
OAuthIntrospectRequest:
type: object
description: |
OAuth 2.0 Token Introspection Request (RFC 7662).
Check if a token is active and get its metadata.
properties:
token:
type: string
description: The token to introspect
token_type_hint:
type: string
enum:
- access_token
- refresh_token
description: Hint about token type
client_id:
type: string
description: Client ID
client_secret:
type: string
description: Client secret
required:
- token
- client_id
OAuthIntrospectResponse:
type: object
description: |
OAuth 2.0 Token Introspection Response (RFC 7662).
Contains token metadata if active, or just `active: false` if not.
properties:
active:
type: boolean
description: Whether the token is currently active
scope:
type: string
description: Scopes granted to the token
client_id:
type: string
description: Client ID the token was issued to
username:
type: string
description: User identifier (if user-based token)
token_type:
type: string
description: Token type
exp:
type: integer
description: Token expiration timestamp (Unix epoch)
iat:
type: integer
description: Token issuance timestamp (Unix epoch)
nbf:
type: integer
description: Token not-before timestamp (Unix epoch)
user_id:
type: string
description: User ID
aud:
type: string
description: Audience (client ID)
iss:
type: string
description: Issuer URL
jti:
type: string
description: Unique token identifier
required:
- active
OAuthErrorResponse:
type: object
description: |
OAuth 2.0 Error Response (RFC 6749 Section 5.2).
Standard error format for OAuth endpoints.
properties:
error:
type: string
description: |
Error code. Common values:
- `invalid_request` - Missing or invalid parameter
- `invalid_client` - Client authentication failed
- `invalid_grant` - Invalid authorization code or refresh token
- `unauthorized_client` - Client not authorized for this grant type
- `unsupported_grant_type` - Grant type not supported
- `invalid_scope` - Requested scope is invalid or exceeds allowed
- `access_denied` - User denied authorization
enum:
- invalid_request
- invalid_client
- invalid_grant
- unauthorized_client
- unsupported_grant_type
- invalid_scope
- access_denied
- server_error
error_description:
type: string
description: Human-readable error description
error_uri:
type: string
format: uri
description: URI with more information about the error
state:
type: string
description: State parameter from the authorization request
required:
- error
OAuthUserInfoResponse:
type: object
description: |
OpenID Connect UserInfo Response.
Contains claims about the authenticated user.
properties:
user_id:
type: string
description: User ID
name:
type: string
description: Full name
given_name:
type: string
description: First name
family_name:
type: string
description: Last name
email:
type: string
format: email
description: Email address
email_verified:
type: boolean
description: Whether email has been verified
picture:
type: string
format: uri
description: Profile picture URL
updated_at:
type: integer
description: Last profile update timestamp (Unix epoch)
required:
- user_id
CreateOAuthAppRequest:
type: object
description: |
Request to create a new OAuth app (`createAppSchema` in `oauth.validators.ts`).
**Required:** `name`, `allowedScopes`. **Optional:** `description`, `redirectUris`, `allowedGrantTypes`,
`homepageUrl`, `privacyPolicyUrl`, `termsOfServiceUrl`, `isConfidential`, `accessTokenLifetime`, `refreshTokenLifetime`.
**Redirect rule (Zod refine):** If the effective grant list includes `authorization_code`
(including when `allowedGrantTypes` is omitted — defaults to `authorization_code` + `refresh_token`),
at least one redirect URI is required. If grants exclude `authorization_code`, `redirectUris` may be omitted.
properties:
name:
type: string
description: App name (displayed to users during authorization)
minLength: 1
maxLength: 100
example: My Integration App
description:
type: string
description: App description
maxLength: 500
example: Integrates PipesHub with our internal tools
redirectUris:
type: array
items:
type: string
format: uri
description: |
Allowed redirect URIs (max 10). Required when an effective grant list includes `authorization_code`
(including the default when `allowedGrantTypes` is omitted).
maxItems: 10
example:
- https://myapp.com/callback
- http://localhost:3000/callback
allowedGrantTypes:
type: array
items:
type: string
enum:
- authorization_code
- client_credentials
- refresh_token
description: |
Allowed grant types. Defaults to `["authorization_code", "refresh_token"]` if omitted (applied by the service, not Zod).
example:
- authorization_code
- refresh_token
allowedScopes:
type: array
items:
type: string
description: Scopes the app can request (non-empty)
minItems: 1
example:
- openid
- profile
- read:records
homepageUrl:
type: string
format: uri
description: App homepage URL (shown during authorization)
privacyPolicyUrl:
type: string
format: uri
description: Privacy policy URL
termsOfServiceUrl:
type: string
format: uri
description: Terms of service URL
isConfidential:
type: boolean
description: |
Whether the app can securely store secrets.
- `true`: Server-side app (secret required for token requests)
- `false`: Browser/mobile app (must use PKCE)
default: true
accessTokenLifetime:
type: integer
description: Access token lifetime in seconds (300–86400)
minimum: 300
maximum: 86400
default: 3600
example: 3600
refreshTokenLifetime:
type: integer
description: Refresh token lifetime in seconds (3600–31536000)
minimum: 3600
maximum: 31536000
default: 2592000
example: 2592000
required:
- name
- allowedScopes
UpdateOAuthAppRequest:
type: object
description: |
Request to update an OAuth app (`updateAppSchema` in `oauth.validators.ts`).
All fields are optional — include only fields that should change. URL fields (`homepageUrl`, `privacyPolicyUrl`, `termsOfServiceUrl`) accept `null` to clear them (nullable in Zod).
**Redirect rule (Zod refine):** If `allowedGrantTypes` includes `authorization_code` and `redirectUris` is present in the body, `redirectUris` must contain at least one URI.
properties:
name:
type: string
description: App name
minLength: 1
maxLength: 100
description:
type: string
description: App description
maxLength: 500
redirectUris:
type: array
items:
type: string
format: uri
description: |
Allowed redirect URIs (up to 10). Required when `authorization_code` grant type is enabled.
Preserved in the database even if `authorization_code` is removed from grant types.
maxItems: 10
allowedGrantTypes:
type: array
items:
type: string
enum:
- authorization_code
- client_credentials
- refresh_token
allowedScopes:
type: array
items:
type: string
minItems: 1
homepageUrl:
type: string
format: uri
nullable: true
privacyPolicyUrl:
type: string
format: uri
nullable: true
termsOfServiceUrl:
type: string
format: uri
nullable: true
accessTokenLifetime:
type: integer
minimum: 300
maximum: 86400
refreshTokenLifetime:
type: integer
minimum: 3600
maximum: 31536000
OAuthAppResponse:
type: object
description: |
OAuth app details (without secret). Fields under `required:` always appear
in `toAppResponse` (`oauth.app.service.ts`); optional URL/description fields
are only present when set by the caller.
required:
- id
- slug
- clientId
- name
- redirectUris
- allowedGrantTypes
- allowedScopes
- status
- isConfidential
- accessTokenLifetime
- refreshTokenLifetime
- createdAt
- updatedAt
properties:
id:
type: string
description: App ID
slug:
type: string
description: URL-friendly app slug
clientId:
type: string
description: OAuth client ID
name:
type: string
description: App name
description:
type: string
description: App description
redirectUris:
type: array
items:
type: string
format: uri
description: Allowed redirect URIs (always returned; may be empty)
allowedGrantTypes:
type: array
items:
type: string
description: Allowed grant types
allowedScopes:
type: array
items:
type: string
description: Allowed scopes
status:
type: string
enum:
- active
- suspended
- revoked
description: App status
homepageUrl:
type: string
format: uri
description: App homepage
privacyPolicyUrl:
type: string
format: uri
description: Privacy policy URL
termsOfServiceUrl:
type: string
format: uri
description: Terms of service URL
isConfidential:
type: boolean
description: Whether app is a confidential client
accessTokenLifetime:
type: integer
description: Access token lifetime in seconds
refreshTokenLifetime:
type: integer
description: Refresh token lifetime in seconds
createdAt:
type: string
format: date-time
description: Creation timestamp
updatedAt:
type: string
format: date-time
description: Last update timestamp
OAuthAppWithSecret:
allOf:
- $ref: '#/components/schemas/OAuthAppResponse'
- type: object
properties:
clientSecret:
type: string
description: |
Client secret (only shown on creation and secret regeneration).
Store this securely - it cannot be retrieved later.
required:
- clientSecret
CreateOAuthAppResponse:
type: object
description: |
Response body for `POST /oauth-clients` (`oauth.app.controller.ts` `createApp`).
The new app (including one-time `clientSecret`) is nested under `app`.
required:
- message
- app
properties:
message:
type: string
example: OAuth app created successfully
app:
$ref: '#/components/schemas/OAuthAppWithSecret'
RegenerateOAuthAppSecretResponse:
type: object
description: |
Response body for `POST /oauth-clients/{appId}/regenerate-secret` (`regenerateSecret`).
required:
- message
- clientId
- clientSecret
properties:
message:
type: string
example: Client secret regenerated successfully
clientId:
type: string
description: OAuth client ID (unchanged)
clientSecret:
type: string
description: New client secret (store securely; previous secret is invalidated)
UpdateOAuthAppResponse:
type: object
description: |
Response body for `PUT /oauth-clients/{appId}` (`oauth.app.controller.ts` `updateApp`).
Updated app (never includes `clientSecret`) is nested under `app`.
required:
- message
- app
properties:
message:
type: string
example: OAuth app updated successfully
app:
$ref: '#/components/schemas/OAuthAppResponse'
SuspendOAuthAppResponse:
type: object
description: |
Response body for `POST /oauth-clients/{appId}/suspend`
(`oauth.app.controller.ts` `suspendApp`). Suspended app (never includes
`clientSecret`) is nested under `app`.
required:
- message
- app
properties:
message:
type: string
example: OAuth app suspended successfully
app:
$ref: '#/components/schemas/OAuthAppResponse'
ActivateOAuthAppResponse:
type: object
description: |
Response body for `POST /oauth-clients/{appId}/activate`
(`oauth.app.controller.ts` `activateApp`). Re-activated app (never includes
`clientSecret`) is nested under `app`.
required:
- message
- app
properties:
message:
type: string
example: OAuth app activated successfully
app:
$ref: '#/components/schemas/OAuthAppResponse'
OAuthAppListResponse:
type: object
description: Paginated list of OAuth apps
required:
- data
- pagination
properties:
data:
type: array
items:
$ref: '#/components/schemas/OAuthAppResponse'
description: List of OAuth apps
pagination:
type: object
required:
- page
- limit
- total
- totalPages
properties:
page:
type: integer
description: Current page number
limit:
type: integer
description: Items per page
total:
type: integer
description: Total number of items
totalPages:
type: integer
description: Total number of pages
OAuthScopeInfo:
type: object
description: Information about an OAuth scope
properties:
name:
type: string
description: Scope identifier
example: openid
description:
type: string
description: Human-readable scope description
example: OpenID Connect authentication
category:
type: string
description: Scope category for grouping (matches the key under `scopes` on list responses)
example: Identity
requiresUserConsent:
type: boolean
description: Whether end-user consent is required when this scope is requested
example: false
required:
- name
- description
- category
- requiresUserConsent
OAuthScopesGroupedResponse:
type: object
description: |
OAuth scopes available to the signed-in user for app registration, grouped by category label.
Category keys are UI labels (e.g. `Identity`, `Knowledge Base`); each maps to a list of scopes in that group.
Categories defined in server config may appear with an **empty array** when every scope in that category is restricted for the caller's role (e.g. non–org-admin users never receive admin-only scopes).
properties:
scopes:
type: object
description: Map of category display name to scopes in that category
additionalProperties:
type: array
items:
$ref: '#/components/schemas/OAuthScopeInfo'
required:
- scopes
OAuthClientManagementRateLimitError:
type: object
description: JSON body when OAuth client management routes exceed the per-minute rate limit (same limiter as other `/oauth-clients/*` routes).
required:
- error
properties:
error:
type: object
required:
- code
- message
properties:
code:
type: string
example: TOO_MANY_REQUESTS
message:
type: string
example: Too many OAuth client requests. Please try again later.
retryAfter:
type: integer
nullable: true
description: Seconds until the limit window resets (when `Retry-After` is present); may be null.
ApplicationJsonErrorResponse:
type: object
description: |
Standard JSON error envelope from `ErrorMiddleware` for `BaseError` subclasses (`error.middleware.ts`).
Returned for most API 4xx errors (unauthorized, forbidden, not found, validation failures, etc.).
required:
- error
properties:
error:
type: object
required:
- code
- message
properties:
code:
type: string
description: Machine-readable code (e.g. `HTTP_UNAUTHORIZED`, `HTTP_FORBIDDEN`).
message:
type: string
metadata:
type: object
description: Optional; may appear in non-production for some errors.
additionalProperties: true
OAuthTokenListItem:
type: object
description: |
Information about an issued token (one element returned by `listTokensForApp`
in `oauth_token.service.ts`). `userId` is omitted for client-credentials access
tokens; all other fields are always populated.
required:
- id
- tokenType
- scopes
- createdAt
- expiresAt
- isRevoked
properties:
id:
type: string
description: Token ID
tokenType:
type: string
enum:
- access
- refresh
description: Type of token
userId:
type: string
description: User ID (omitted for client-credentials access tokens)
scopes:
type: array
items:
type: string
description: Granted scopes
createdAt:
type: string
format: date-time
description: Token creation time
expiresAt:
type: string
format: date-time
description: Token expiration time
isRevoked:
type: boolean
description: Whether token has been revoked
OAuthAppTokensListResponse:
type: object
description: |
Response body for `GET /oauth-clients/{appId}/tokens` (`listAppTokens`).
required:
- tokens
properties:
tokens:
type: array
items:
$ref: '#/components/schemas/OAuthTokenListItem'
description: Active access and refresh tokens for the app
Address:
type: object
additionalProperties: false
properties:
_id:
type: string
format: ObjectId
description: Optional address document id
addressLine1:
type: string
description: Address line 1
city:
type: string
description: City
state:
type: string
description: State/Province
postCode:
type: string
description: Postal/ZIP code
country:
type: string
description: Country
Organization:
type: object
properties:
_id:
type: string
format: ObjectId
description: Unique organization identifier
slug:
type: string
description: Unique slug for the organization
registeredName:
type: string
description: Registered name
shortName:
type: string
description: Short name or display name
domain:
type: string
description: Organization domain
contactEmail:
type: string
format: email
description: Contact email address
accountType:
type: string
enum:
- individual
- business
description: Type of account
permanentAddress:
$ref: '#/components/schemas/Address'
onBoardingStatus:
type: string
enum:
- configured
- notConfigured
- skipped
description: Onboarding status
isDeleted:
type: boolean
description: Soft delete flag
default: false
__v:
type: integer
description: Document version (MongoDB)
createdAt:
type: string
format: date-time
description: Creation timestamp (ISO 8601)
updatedAt:
type: string
format: date-time
description: Last update timestamp (ISO 8601)
required:
- _id
- slug
- registeredName
- domain
- contactEmail
- accountType
- onBoardingStatus
- isDeleted
- createdAt
- updatedAt
- __v
KnowledgeBaseCreateResponse:
type: object
additionalProperties: false
description: Response returned when a knowledge base is created
properties:
id:
type: string
description: Knowledge base ID
name:
type: string
description: Knowledge base name
createdAtTimestamp:
type: integer
format: int64
description: Creation timestamp in milliseconds
updatedAtTimestamp:
type: integer
format: int64
description: Last update timestamp in milliseconds
userRole:
type: string
enum:
- OWNER
- WRITER
- READER
description: User's role in this knowledge base
required:
- id
- name
- createdAtTimestamp
- updatedAtTimestamp
- userRole
FolderCreateResponseSchema:
type: object
additionalProperties: false
description: Response returned when a folder is created (root or nested subfolder)
properties:
id:
type: string
description: Unique folder identifier
name:
type: string
description: Name of the folder
required:
- id
- name
FolderUpdateResponseSchema:
type: object
additionalProperties: false
description: Response returned by PUT /knowledgeBase/{kbId}/folder/{folderId} (updateFolder).
required:
- success
- message
properties:
success:
type: boolean
example: true
message:
type: string
example: Folder updated successfully
FolderDeleteResponseSchema:
type: object
additionalProperties: false
description: Response returned by DELETE /knowledgeBase/{kbId}/folder/{folderId} (deleteFolder).
required:
- success
- message
properties:
success:
type: boolean
example: true
message:
type: string
example: Folder deleted successfully
KnowledgeBaseMoveRecordRequestBody:
type: object
additionalProperties: false
description: Request body for PUT /knowledgeBase/{kbId}/record/{recordId}/move (moveRecord).
required:
- newParentId
properties:
newParentId:
type: string
nullable: true
description: Target folder ID, or null to move the record to the knowledge base root
KnowledgeBaseMoveRecordResponse:
type: object
additionalProperties: false
description: Response returned by PUT /knowledgeBase/{kbId}/record/{recordId}/move (moveRecord).
required:
- success
- message
properties:
success:
type: boolean
example: true
message:
type: string
example: Record moved successfully
GetAllKnowledgeBaseResponseSchema:
type: object
additionalProperties: false
description: Response returned by GET /knowledgeBase (listKnowledgeBases).
required:
- knowledgeBases
- pagination
- filters
properties:
knowledgeBases:
type: array
items:
type: object
additionalProperties: false
required:
- id
- name
- connectorId
- createdAtTimestamp
- updatedAtTimestamp
- createdBy
- userRole
- folders
properties:
id:
type: string
name:
type: string
connectorId:
type: string
nullable: true
createdAtTimestamp:
type: integer
format: int64
updatedAtTimestamp:
type: integer
format: int64
createdBy:
type: string
userRole:
type: string
enum:
- OWNER
- WRITER
- READER
folders:
type: array
items:
type: object
additionalProperties: false
required:
- id
- name
properties:
id:
type: string
name:
type: string
createdAtTimestamp:
type: integer
format: int64
path:
type: string
pagination:
type: object
additionalProperties: false
required:
- page
- limit
- totalCount
- totalPages
- hasNext
- hasPrev
properties:
page:
type: integer
limit:
type: integer
totalCount:
type: integer
totalPages:
type: integer
hasNext:
type: boolean
hasPrev:
type: boolean
filters:
type: object
additionalProperties: false
required:
- applied
- available
properties:
applied:
type: object
additionalProperties: false
description: |
Active filters. Empty `{}` when defaults. Keys use snake_case for sort
fields (backend convention in kb_service.py).
properties:
search:
type: string
permissions:
type: array
items:
type: string
enum:
- OWNER
- WRITER
- READER
sort_by:
type: string
enum:
- name
- createdAtTimestamp
- updatedAtTimestamp
- userRole
sort_order:
type: string
enum:
- asc
- desc
available:
type: object
additionalProperties: false
required:
- permissions
- sortFields
- sortOrders
properties:
permissions:
type: array
items:
type: string
enum:
- OWNER
- WRITER
- READER
sortFields:
type: array
items:
type: string
enum:
- name
- createdAtTimestamp
- updatedAtTimestamp
- userRole
sortOrders:
type: array
items:
type: string
enum:
- asc
- desc
GetKnowledgeBaseById:
type: object
additionalProperties: false
description: Response returned by GET /knowledgeBase/{kbId} (getKnowledgeBase).
required:
- id
- name
- connectorId
- createdAtTimestamp
- updatedAtTimestamp
- createdBy
- userRole
- folders
properties:
id:
type: string
description: Knowledge base ID
name:
type: string
description: Knowledge base name
connectorId:
type: string
nullable: true
description: Associated connector ID (null for manual KBs)
createdAtTimestamp:
type: integer
format: int64
description: Creation timestamp in milliseconds
updatedAtTimestamp:
type: integer
format: int64
description: Last update timestamp in milliseconds
createdBy:
type: string
description: User ID of the creator
userRole:
type: string
enum:
- OWNER
- WRITER
- READER
description: User's role in this knowledge base
folders:
type: array
description: Root-level folders in this knowledge base
items:
type: object
additionalProperties: false
required:
- id
- name
properties:
id:
type: string
description: Folder ID
name:
type: string
description: Folder name
createdAtTimestamp:
type: integer
format: int64
description: Creation timestamp in milliseconds
UpdateKnowledgeBaseById:
type: object
additionalProperties: false
description: Response returned by PUT /knowledgeBase/{kbId} (updateKnowledgeBase).
required:
- success
- message
properties:
success:
type: boolean
example: true
message:
type: string
example: Knowledge base updated successfully
DeleteKnowledgeBaseById:
type: object
additionalProperties: false
description: Response returned by DELETE /knowledgeBase/{kbId} (deleteKnowledgeBase).
required:
- success
- message
properties:
success:
type: boolean
example: true
message:
type: string
example: Knowledge base deleted successfully
RecordTypeEnum:
type: string
description: |
Type of content. Mirrors the backend `RecordType` enum
(`backend/python/app/models/entities.py`); connector-sourced records
may use any of the connector-specific types below.
- FILE: Uploaded or synced documents (PDF, DOCX, etc.)
- DRIVE: Drive/folder container (Google Drive, OneDrive, etc.)
- WEBPAGE: Web pages crawled or bookmarked
- DATABASE: Database object (e.g. Notion database)
- DATASOURCE: Data source object
- MESSAGE: Chat/messaging content (Slack, Teams)
- MAIL: Email messages (Gmail, Outlook)
- GROUP_MAIL: Group/shared mailbox email messages
- TICKET: Support/issue tickets (Jira, ServiceNow)
- COMMENT: Comments from collaboration tools
- INLINE_COMMENT: Inline comments anchored to content (e.g. Confluence)
- CONFLUENCE_PAGE: Confluence page
- CONFLUENCE_BLOGPOST: Confluence blog post
- SHAREPOINT_PAGE: SharePoint page
- SHAREPOINT_LIST: SharePoint list
- SHAREPOINT_LIST_ITEM: SharePoint list item
- SHAREPOINT_DOCUMENT_LIBRARY: SharePoint document library
- LINK: Web link / bookmark
- PROJECT: Project entity (e.g. Jira project)
- PULL_REQUEST: Source-control pull request
- MEETING: Meeting record (e.g. Zoom)
- PRODUCT: Product entity (CRM)
- DEAL: Deal/opportunity entity (CRM)
- CASE: Case entity (CRM/support)
- TASK: Task entity
- ARTIFACT: Generated/derived artifact
- CODE_FILE: Source-code file
- SQL_TABLE: SQL table object
- SQL_VIEW: SQL view object
- OTHERS: Miscellaneous content types
enum:
- FILE
- DRIVE
- WEBPAGE
- DATABASE
- DATASOURCE
- MESSAGE
- MAIL
- GROUP_MAIL
- TICKET
- COMMENT
- INLINE_COMMENT
- CONFLUENCE_PAGE
- CONFLUENCE_BLOGPOST
- SHAREPOINT_PAGE
- SHAREPOINT_LIST
- SHAREPOINT_LIST_ITEM
- SHAREPOINT_DOCUMENT_LIBRARY
- LINK
- PROJECT
- PULL_REQUEST
- MEETING
- PRODUCT
- DEAL
- CASE
- TASK
- ARTIFACT
- CODE_FILE
- SQL_TABLE
- SQL_VIEW
- OTHERS
example: FILE
ConnectorNameEnum:
type: string
description: |
Name of the source connector. Mirrors the values of the backend
`Connectors` enum (`backend/python/app/config/constants/arangodb.py`);
records store the enum value (e.g. Google Drive is `DRIVE`,
SharePoint Online is `SHAREPOINT ONLINE`), not the enum member name.
enum:
- DRIVE
- DRIVE WORKSPACE
- GMAIL
- GMAIL WORKSPACE
- CALENDAR
- ONEDRIVE
- SHAREPOINT ONLINE
- OUTLOOK
- OUTLOOK PERSONAL
- OUTLOOK CALENDAR
- MICROSOFT TEAMS
- NOTION
- SLACK
- SLACK WORKSPACE
- KB
- CONFLUENCE
- CONFLUENCE DATA CENTER
- CONFLUENCE DATA CENTER PERSONAL
- JIRA
- JIRA PERSONAL
- JIRA DATA CENTER
- JIRA DATA CENTER PERSONAL
- BOX
- NEXTCLOUD
- DROPBOX
- DROPBOX PERSONAL
- WEB
- BOOKSTACK
- GITHUB
- SERVICENOW
- SALESFORCE
- S3
- MINIO
- GCS
- AZURE BLOB
- AZURE FILES
- LINEAR
- ZAMMAD
- ZOOM
- GITLAB
- GITLAB PERSONAL
- SNOWFLAKE
- POSTGRESQL
- MARIADB
- UNKNOWN
- RSS
- LOCAL_FS
- CODING_SANDBOX
- DATABASE_SANDBOX
- IMAGE_GENERATION
- ATTACHMENTS
example: DRIVE
Record:
type: object
description: |
A record represents a single document, file, or content item within a knowledge base.
Records can originate from file uploads or external connectors (Google Drive, OneDrive, etc.).
properties:
id:
type: string
description: Unique record identifier (UUID format)
example: 550e8400-e29b-41d4-a716-446655440000
recordName:
type: string
description: Display name of the record
example: Q4 Financial Report.pdf
name:
type: string
description: Display name (alias for recordName)
externalRecordId:
type: string
description: External storage document ID (links to Storage module)
example: 507f1f77bcf86cd799439011
recordType:
$ref: '#/components/schemas/RecordTypeEnum'
origin:
type: string
enum:
- UPLOAD
- CONNECTOR
description: |
Source of the record:
- UPLOAD: Manually uploaded via API/UI
- CONNECTOR: Synced from external connector
example: UPLOAD
connectorId:
type: string
description: ID of the connector that synced this record (null for uploads)
example: conn_123456
connectorName:
$ref: '#/components/schemas/ConnectorNameEnum'
orgId:
type: string
description: Organization ID that owns this record
example: org_abc123
kbId:
type: string
description: Knowledge base ID containing this record
example: kb_xyz789
folderId:
type: string
nullable: true
description: Parent folder ID (null if at KB root)
example: folder_456
version:
type: integer
description: Current version number (increments on updates)
default: 0
example: 3
isLatestVersion:
type: boolean
description: Whether this is the latest version
createdAtTimestamp:
type: integer
format: int64
description: Creation timestamp in milliseconds
example: 1704153600000
updatedAtTimestamp:
type: integer
format: int64
description: Last update timestamp in milliseconds
example: 1704240000000
sourceCreatedAtTimestamp:
type: integer
format: int64
description: Source creation timestamp (from connector)
sourceLastModifiedTimestamp:
type: integer
format: int64
description: Source last modified timestamp (from connector)
indexingStatus:
type: string
enum:
- NOT_STARTED
- PAUSED
- IN_PROGRESS
- COMPLETED
- FAILED
- FILE_TYPE_NOT_SUPPORTED
- AUTO_INDEX_OFF
- EMPTY
- ENABLE_MULTIMODAL_MODELS
- QUEUED
description: |
Current indexing/processing status:
- NOT_STARTED: Awaiting indexing
- QUEUED: In indexing queue
- IN_PROGRESS: Currently being indexed
- COMPLETED: Successfully indexed and searchable
- FAILED: Indexing failed (check error details)
- PAUSED: Indexing paused by user
- FILE_TYPE_NOT_SUPPORTED: Unsupported file format
- AUTO_INDEX_OFF: Auto-indexing disabled for this record
- EMPTY: File has no extractable content
- ENABLE_MULTIMODAL_MODELS: Requires multimodal AI models
example: COMPLETED
isDeleted:
type: boolean
description: Soft delete flag
default: false
isArchived:
type: boolean
description: Archive flag for inactive records
default: false
webUrl:
type: string
format: uri
description: Direct URL to access the original content
example: https://drive.google.com/file/d/abc123
mimeType:
type: string
description: MIME type of the file content
example: application/pdf
sizeInBytes:
type: integer
format: int64
description: File size in bytes
example: 1048576
extension:
type: string
description: File extension (without dot)
example: pdf
sha256Hash:
type: string
description: SHA-256 hash for content deduplication
type:
type: string
description: Node type identifier
example: record
fileRecord:
type: object
nullable: true
description: File-specific metadata (present when recordType is FILE)
properties:
id:
type: string
name:
type: string
extension:
type: string
mimeType:
type: string
sizeInBytes:
type: integer
format: int64
webUrl:
type: string
path:
type: string
nullable: true
isFile:
type: boolean
mailRecord:
type: object
nullable: true
description: Email-specific metadata (present when recordType is MAIL or GROUP_MAIL)
ticketRecord:
type: object
nullable: true
description: Ticket-specific metadata (present when recordType is TICKET)
additionalProperties: true
required:
- recordName
- recordType
- origin
- orgId
UpdateRecordEnrichment:
type: object
description: |
Fields merged into successful record-update responses (Node gateway and Local KB connector).
properties:
timestamp:
type: integer
format: int64
description: Epoch milliseconds when the response was generated
fileUpdated:
type: boolean
location:
type: string
enum:
- kb_root
- folder
kb:
type: object
additionalProperties: true
userPermission:
type: string
GetRecordByIdResponseSchema:
type: object
additionalProperties: false
description: Response returned by GET /knowledgeBase/record/{recordId}.
required:
- record
- knowledgeBase
- folder
- metadata
- permissions
properties:
record:
type: object
additionalProperties: false
required:
- id
- orgId
- recordName
- externalRecordId
- connectorId
- connectorName
- recordType
- origin
- version
- isLatestVersion
- createdAtTimestamp
- updatedAtTimestamp
- sourceCreatedAtTimestamp
- sourceLastModifiedTimestamp
- lastSyncTimestamp
- indexingStatus
- extractionStatus
- isDeleted
- isArchived
- isDirty
- isVLMOcrProcessed
- mimeType
- sizeInBytes
- webUrl
- fileRecord
- mailRecord
- ticketRecord
properties:
id:
type: string
orgId:
type: string
recordName:
type: string
externalRecordId:
type: string
externalRootGroupId:
type: string
nullable: true
externalGroupId:
type: string
nullable: true
connectorId:
type: string
connectorName:
$ref: '#/components/schemas/ConnectorNameEnum'
recordType:
$ref: '#/components/schemas/RecordTypeEnum'
origin:
type: string
version:
type: integer
isLatestVersion:
type: boolean
createdAtTimestamp:
type: integer
format: int64
updatedAtTimestamp:
type: integer
format: int64
sourceCreatedAtTimestamp:
type: integer
format: int64
sourceLastModifiedTimestamp:
type: integer
format: int64
lastSyncTimestamp:
type: integer
format: int64
lastIndexTimestamp:
type: integer
format: int64
lastExtractionTimestamp:
type: integer
format: int64
indexingStatus:
type: string
extractionStatus:
type: string
isDeleted:
type: boolean
isArchived:
type: boolean
isDirty:
type: boolean
isVLMOcrProcessed:
type: boolean
mimeType:
type: string
sizeInBytes:
type: integer
format: int64
md5Checksum:
type: string
virtualRecordId:
type: string
webUrl:
type: string
fileRecord:
type: object
nullable: true
additionalProperties: false
required:
- id
- orgId
- name
- extension
- mimeType
- sizeInBytes
- isFile
- webUrl
properties:
id:
type: string
orgId:
type: string
name:
type: string
extension:
type: string
mimeType:
type: string
sizeInBytes:
type: integer
format: int64
isFile:
type: boolean
webUrl:
type: string
path:
type: string
nullable: true
localFsRelativePath:
type: string
nullable: true
mailRecord:
type: object
nullable: true
additionalProperties: false
properties: {}
ticketRecord:
type: object
nullable: true
additionalProperties: false
properties: {}
knowledgeBase:
type: object
nullable: true
additionalProperties: false
required:
- id
- name
- orgId
properties:
id:
type: string
name:
type: string
orgId:
type: string
folder:
type: object
nullable: true
additionalProperties: false
required:
- id
- name
properties:
id:
type: string
name:
type: string
metadata:
type: object
additionalProperties: false
required:
- languages
- topics
- subcategories1
- subcategories2
- subcategories3
- departments
- categories
properties:
languages:
type: array
items:
type: object
additionalProperties: false
required:
- id
- name
properties:
id:
type: string
name:
type: string
topics:
type: array
items:
type: object
additionalProperties: false
required:
- id
- name
properties:
id:
type: string
name:
type: string
subcategories1:
type: array
items:
type: object
additionalProperties: false
required:
- id
- name
properties:
id:
type: string
name:
type: string
subcategories2:
type: array
items:
type: object
additionalProperties: false
required:
- id
- name
properties:
id:
type: string
name:
type: string
subcategories3:
type: array
items:
type: object
additionalProperties: false
required:
- id
- name
properties:
id:
type: string
name:
type: string
departments:
type: array
items:
type: object
additionalProperties: false
required:
- id
- name
properties:
id:
type: string
name:
type: string
categories:
type: array
items:
type: object
additionalProperties: false
required:
- id
- name
properties:
id:
type: string
name:
type: string
permissions:
type: array
items:
type: object
additionalProperties: false
required:
- id
- name
- type
- relationship
- accessType
properties:
id:
type: string
name:
type: string
type:
type: string
relationship:
type: string
enum:
- OWNER
- WRITER
- READER
accessType:
type: string
DeleteRecordResponseSchema:
type: object
additionalProperties: false
description: Response returned by DELETE /knowledgeBase/record/{recordId}.
required:
- success
- message
- recordId
properties:
success:
type: boolean
enum:
- true
message:
type: string
recordId:
type: string
connector:
type: string
nullable: true
timestamp:
type: integer
format: int64
nullable: true
reIndexRecordResponseSchema:
type: object
additionalProperties: false
description: Response returned by POST /knowledgeBase/reindex/record/{recordId}.
required:
- success
- message
- eventPublished
- depth
properties:
success:
type: boolean
enum:
- true
message:
type: string
recordId:
type: string
nullable: true
recordName:
type: string
nullable: true
connector:
type: string
nullable: true
eventPublished:
type: boolean
userRole:
type: string
nullable: true
depth:
type: integer
ReIndexRecordGroupResponseSchema:
type: object
additionalProperties: false
description: Response returned by POST /knowledgeBase/reindex/record-group/{recordGroupId}.
required:
- success
- message
- recordGroupId
- depth
- eventPublished
properties:
success:
type: boolean
enum:
- true
message:
type: string
recordGroupId:
type: string
depth:
type: integer
connector:
type: string
nullable: true
eventPublished:
type: boolean
UploadLimitsResponseSchema:
type: object
additionalProperties: false
description: Upload constraints returned by GET /knowledgeBase/limits.
required:
- maxFilesPerRequest
- maxFileSizeBytes
properties:
maxFilesPerRequest:
type: integer
minimum: 1
example: 1000
description: Maximum number of files per upload request
maxFileSizeBytes:
type: integer
minimum: 1
example: 31457280
description: Maximum file size in bytes (default 30MB when platform settings unavailable)
UploadStreamSSEEvent:
type: object
description: |
Server-Sent Event envelope for the KB streaming upload endpoint
(`POST /knowledgeBase/{kbId}/upload`, with optional `folderId` query param).
These endpoints respond with `Content-Type: text/event-stream`: the upload
and its per-file progress are a single request. The body streams one
terminal event per file, then a final `done` summary, then closes. `data`
is a JSON-encoded string whose decoded shape depends on `event`:
- `file:succeeded` — see `UploadSucceededFileDetail`. The file was
uploaded and its record created; content indexing then continues
asynchronously.
- `file:failed` — see `UploadFailedFileDetail`. Covers files rejected up
front (oversize / unsupported type — these carry `reason`), files that
failed the storage upload (`stage: "upload"`), and files the indexing
service could not create (`stage: "index"`).
- `done` — see `UploadDoneSummary`. Final event; the stream closes after it.
- `error` — `{ "message": string }`. Emitted only on a catastrophic
mid-stream failure (after the 200 headers were already sent), then the
stream closes. Clients MUST treat any file without a terminal
`file:succeeded` / `file:failed` as failed when this is received.
The stream also emits SSE comment heartbeats (`: keepalive`) roughly every
1s during slow work; these carry no `event`/`data` and should be ignored.
Authentication, permission, and request-shape failures occur BEFORE the
stream starts and are returned as ordinary 4xx JSON errors (not stream
events).
properties:
event:
type: string
enum:
- file:succeeded
- file:failed
- done
- error
data:
type: string
description: JSON-encoded event payload. Shape depends on `event`.
IndexingStatusFilter:
type: string
description: |
Indexing status used to filter which records are included in a scoped
reindex (record or record-group). Omit `statusFilters` to reindex all
descendants regardless of status.
enum:
- NOT_STARTED
- QUEUED
- IN_PROGRESS
- COMPLETED
- FAILED
- FILE_TYPE_NOT_SUPPORTED
- AUTO_INDEX_OFF
- EMPTY
ReindexRecordRequestBody:
type: object
description: Optional body for single-record reindex.
properties:
depth:
type: integer
minimum: -1
maximum: 100
default: 0
description: |
Child traversal depth (`0` = record only; higher values include
descendants; `100` is used by clients for folder-like reindex).
force:
type: boolean
default: false
description: Force reindex even when the connector considers the record unchanged.
statusFilters:
type: array
items:
$ref: '#/components/schemas/IndexingStatusFilter'
description: |
When set, only records whose indexing status matches one of these
values are reindexed (applies to the record and its descendants per `depth`).
ReindexRecordGroupRequestBody:
type: object
description: Optional body for record-group (folder/KB container) reindex.
properties:
depth:
type: integer
minimum: -1
maximum: 100
default: 0
description: Depth of records under the record group to include.
force:
type: boolean
default: false
description: Force reindex for all matched records in the group.
statusFilters:
type: array
items:
$ref: '#/components/schemas/IndexingStatusFilter'
description: |
When set, only records matching these indexing statuses are reindexed.
DateRangeFilter:
type: object
description: Date range filter with optional inclusive bounds (epoch ms).
properties:
gte:
type: integer
nullable: true
description: Greater-than-or-equal bound (epoch ms).
lte:
type: integer
nullable: true
description: Less-than-or-equal bound (epoch ms).
SizeRangeFilter:
type: object
description: Size range filter with optional inclusive bounds (bytes).
properties:
gte:
type: integer
nullable: true
description: Greater-than-or-equal bound (bytes).
lte:
type: integer
nullable: true
description: Less-than-or-equal bound (bytes).
FilterOption:
type: object
description: A single filter option for knowledge hub filters.
required:
- id
- label
properties:
id:
type: string
description: Filter ID value to send in requests.
label:
type: string
description: Display label for the filter.
type:
type: string
nullable: true
description: Additional type information (currently unused, may be null).
connectorType:
type: string
nullable: true
description: Connector type/name. Set only for entries in the `connectors` list.
KnowledgeHubNode:
type: object
description: |
One element of `items`. The live API keeps keys stable and sets
inapplicable values to JSON `null` (not omitted).
required:
- id
- name
- nodeType
- parentId
- origin
- connector
- recordType
- recordGroupType
- indexingStatus
- reason
- createdAt
- updatedAt
- sizeInBytes
- mimeType
- extension
- webUrl
- hasChildren
- previewRenderable
- permission
- sharingStatus
- isInternal
properties:
id:
type: string
description: Unique identifier for the node.
name:
type: string
description: Display name of the node.
nodeType:
type: string
enum:
- app
- recordGroup
- folder
- record
description: Type of the node (app, recordGroup, folder, or record).
parentId:
type: string
nullable: true
description: Parent node ID, or `null` at the root browse level.
origin:
type: string
enum:
- COLLECTION
- CONNECTOR
description: Origin type.
connector:
type: string
nullable: true
description: Connector display name / key when applicable; otherwise `null`.
recordType:
type: string
nullable: true
description: Record type when `nodeType` is `record`; otherwise `null`.
recordGroupType:
type: string
nullable: true
description: Record group type when `nodeType` is `recordGroup`; otherwise `null`.
indexingStatus:
type: string
nullable: true
description: Indexing status when `nodeType` is `record`; otherwise `null`.
reason:
type: string
nullable: true
description: Failure or status reason when set; otherwise `null`.
isInternal:
type: boolean
description: True for internal/system nodes that do not originate from a source.
createdAt:
type: integer
description: Creation timestamp (epoch ms).
updatedAt:
type: integer
description: Update timestamp (epoch ms).
sizeInBytes:
type: integer
nullable: true
description: File size in bytes for file records; otherwise `null`.
mimeType:
type: string
nullable: true
extension:
type: string
nullable: true
webUrl:
type: string
nullable: true
hasChildren:
type: boolean
description: Whether the node has children (sidebar / tree).
previewRenderable:
type: boolean
nullable: true
permission:
type: object
nullable: true
description: Per-item permission when `include=permissions` is requested; otherwise `null`.
required:
- role
- canEdit
- canDelete
properties:
role:
type: string
canEdit:
type: boolean
canDelete:
type: boolean
sharingStatus:
type: string
nullable: true
description: |
Sharing status (e.g. `private`, `shared`, `team`, `workspace`) when
applicable; otherwise `null`.
KnowledgeHubNodesResponse:
type: object
description: |
Response body for the Knowledge Hub nodes API. The deployed service
serialises optional values as JSON `null` and always includes the keys
listed in `required` (Swagger / clients will see stable shapes, not
omitted properties).
required:
- success
- error
- id
- currentNode
- parentNode
- items
- pagination
- filters
- breadcrumbs
- counts
- permissions
properties:
success:
type: boolean
enum:
- true
description: Always `true` on HTTP 200. Failures use 4xx/5xx error envelopes, not this body shape.
error:
type: string
nullable: true
description: Always `null` on HTTP 200.
id:
type: string
nullable: true
description: Current parent node ID when browsing children; `null` at root.
currentNode:
type: object
nullable: true
description: Node being browsed when `parentId` is in the path; `null` at root.
required:
- id
- name
- nodeType
properties:
id:
type: string
name:
type: string
nodeType:
type: string
description: One of `app`, `recordGroup`, `folder`, `record`.
subType:
type: string
nullable: true
description: Connector name or record type when applicable; otherwise `null`.
parentNode:
type: object
nullable: true
description: Parent of `currentNode` when present; `null` when not applicable.
required:
- id
- name
- nodeType
properties:
id:
type: string
name:
type: string
nodeType:
type: string
description: One of `app`, `recordGroup`, `folder`, `record`.
subType:
type: string
nullable: true
items:
type: array
description: Page of nodes for the current browse or search.
items:
$ref: '#/components/schemas/KnowledgeHubNode'
pagination:
type: object
required:
- page
- limit
- totalItems
- totalPages
- hasNext
- hasPrev
properties:
page:
type: integer
description: Current page (1-indexed).
limit:
type: integer
description: Page size.
totalItems:
type: integer
totalPages:
type: integer
hasNext:
type: boolean
hasPrev:
type: boolean
filters:
type: object
required:
- applied
- available
properties:
applied:
type: object
description: Echo of applied filters; unused slots are JSON `null`.
required:
- q
- nodeTypes
- recordTypes
- origins
- connectorIds
- indexingStatus
- createdAt
- updatedAt
- size
- sortBy
- sortOrder
properties:
q:
type: string
nullable: true
nodeTypes:
type: array
nullable: true
items:
type: string
recordTypes:
type: array
nullable: true
items:
type: string
origins:
type: array
nullable: true
items:
type: string
connectorIds:
type: array
nullable: true
items:
type: string
indexingStatus:
type: array
nullable: true
items:
type: string
createdAt:
nullable: true
allOf:
- $ref: '#/components/schemas/DateRangeFilter'
updatedAt:
nullable: true
allOf:
- $ref: '#/components/schemas/DateRangeFilter'
size:
nullable: true
allOf:
- $ref: '#/components/schemas/SizeRangeFilter'
sortBy:
type: string
description: Effective sort field after server normalisation.
sortOrder:
type: string
description: Effective sort order after server normalisation.
available:
type: object
nullable: true
description: Populated when `include=availableFilters`; otherwise `null`.
required:
- nodeTypes
- recordTypes
- origins
- connectors
- indexingStatus
- sortBy
- sortOrder
properties:
nodeTypes:
type: array
items:
$ref: '#/components/schemas/FilterOption'
recordTypes:
type: array
items:
$ref: '#/components/schemas/FilterOption'
origins:
type: array
items:
$ref: '#/components/schemas/FilterOption'
connectors:
type: array
items:
$ref: '#/components/schemas/FilterOption'
indexingStatus:
type: array
items:
$ref: '#/components/schemas/FilterOption'
sortBy:
type: array
items:
$ref: '#/components/schemas/FilterOption'
sortOrder:
type: array
items:
$ref: '#/components/schemas/FilterOption'
breadcrumbs:
type: array
nullable: true
description: Present when `include=breadcrumbs`; otherwise `null`.
items:
type: object
required:
- id
- name
- nodeType
properties:
id:
type: string
name:
type: string
nodeType:
type: string
description: One of `app`, `recordGroup`, `folder`, `record`.
subType:
type: string
nullable: true
counts:
type: object
nullable: true
description: Present when `include=counts`; otherwise `null`.
required:
- items
- total
properties:
items:
type: array
items:
type: object
required:
- label
- count
properties:
label:
type: string
count:
type: integer
total:
type: integer
permissions:
type: object
nullable: true
description: Present when `include=permissions`; otherwise `null`.
required:
- role
- canUpload
- canCreateFolders
- canEdit
- canDelete
- canManagePermissions
properties:
role:
type: string
canUpload:
type: boolean
canCreateFolders:
type: boolean
canEdit:
type: boolean
canDelete:
type: boolean
canManagePermissions:
type: boolean
Filters:
type: object
additionalProperties: false
description: |
App connector instance ids and knowledge-base / record-group ids that narrow retrieval
for a turn. For **org assistant** chat streams, send explicit `apps` / `kb` lists.
For **agent** chat streams, send explicit id lists, or **omit** `filters` (and `tools`)
to let the service use the agent’s stored knowledge and tool configuration. Sending
`{ "apps": [], "kb": [] }` on an agent stream means **no** knowledge sources for that
turn (it is not “full org default”).
properties:
apps:
type: array
items:
type: string
description: |
Connector instance ids to scope retrieval for this turn. Each element
must be a UUID (connector instance id, record-group id, etc.) or the
org knowledge-base collection sentinel `knowledgeBase_`
(pattern `knowledgeBase_[a-zA-Z0-9_-]+`). Gateway validation matches
Zod `appOrKbIdSchema`.
kb:
type: array
items:
type: string
description: |
Knowledge-base / record-group ids to scope retrieval for this turn.
Each element uses the same accepted formats as `apps`: a UUID or
`knowledgeBase_` (pattern `knowledgeBase_[a-zA-Z0-9_-]+`).
AppliedFilterNode:
type: object
additionalProperties: false
description: A single filter node selected by the user (used for display/persistence of active filters)
properties:
id:
type: string
description: Unique identifier of the filter node
name:
type: string
description: Display name of the filter node
nodeType:
type: string
description: Type of the node (e.g. app, recordGroup, folder, record)
connector:
type: string
description: Connector identifier associated with this node
AppliedFilters:
type: object
additionalProperties: false
description: |
Rich filter state selected by the user, used for display and persistence only.
This mirrors the active selection shown in the UI and is distinct from the
machine-readable `filters` field used for retrieval scoping.
properties:
apps:
type: array
items:
$ref: '#/components/schemas/AppliedFilterNode'
description: Applied app/connector filter nodes
kb:
type: array
items:
$ref: '#/components/schemas/AppliedFilterNode'
description: Applied knowledge-base filter nodes
ChatAttachmentRef:
type: object
additionalProperties: false
description: |
Reference to an attachment produced by `POST /conversations/attachments/upload`
(or the equivalent agent route). Include in create/stream/message bodies
so the turn is sent with uploaded files.
required:
- recordId
properties:
recordId:
type: string
minLength: 1
description: Attachment record id returned from the upload endpoint.
recordName:
type: string
minLength: 1
description: Original display name of the file when known.
mimeType:
type: string
minLength: 1
description: MIME type of the uploaded file.
extension:
type: string
minLength: 1
description: File extension (e.g. `pdf`).
virtualRecordId:
type: string
minLength: 1
description: Optional synthetic record id used by the graph layer.
ChatAttachmentUploadRef:
type: object
additionalProperties: false
description: |
Concrete attachment metadata returned by `POST /conversations/attachments/upload`
(or the equivalent agent route).
required:
- recordId
- recordName
- mimeType
- extension
- virtualRecordId
properties:
recordId:
type: string
minLength: 1
description: Server-assigned attachment record id.
recordName:
type: string
minLength: 1
description: Original filename stored for the attachment.
mimeType:
type: string
minLength: 1
description: MIME type of the uploaded file.
extension:
type: string
minLength: 1
description: File extension derived by the backend.
virtualRecordId:
type: string
minLength: 1
description: Synthetic record id used by the graph layer.
ocrMode:
type: string
minLength: 1
description: Optional backend-reported processing mode for the attachment.
ChatAttachmentUploadResponse:
type: object
additionalProperties: false
description: |
Success envelope returned by `POST /conversations/attachments/upload`
and `POST /agents/{agentKey}/conversations/attachments/upload`.
required:
- conversationId
- attachments
properties:
conversationId:
type: string
nullable: true
description: |
Existing conversation id echoed from the request when the upload is tied to a thread; otherwise `null`.
attachments:
type: array
minItems: 1
items:
$ref: '#/components/schemas/ChatAttachmentUploadRef'
CreateConversationRequest:
type: object
description: |
Request body for creating a new AI conversation.
**Query Processing:**
The query is processed through PipesHub's AI pipeline which:
- Performs semantic search across indexed knowledge bases
- Retrieves relevant context from matching documents
- Generates a response with citations to source materials
- Suggests follow-up questions based on the conversation
required:
- query
properties:
query:
type: string
minLength: 1
maxLength: 100000
description: |
The user's question or prompt to start the conversation.
Supports natural language queries of any complexity.
example: What are the key findings from our Q4 financial report?
recordIds:
type: array
items:
type: string
format: objectId
description: |
Limit the AI's knowledge scope to specific records/documents.
When provided, only these records will be searched for context.
example:
- 507f1f77bcf86cd799439011
- 507f1f77bcf86cd799439012
filters:
$ref: '#/components/schemas/Filters'
appliedFilters:
$ref: '#/components/schemas/AppliedFilters'
attachments:
type: array
items:
$ref: '#/components/schemas/ChatAttachmentRef'
description: |
Uploaded chat attachments to associate with this conversation turn (see
`POST /conversations/attachments/upload`).
modelKey:
type: string
description: |
Identifier for the AI model configuration to use.
Available models depend on organization settings.
example: gpt-4-turbo
modelName:
type: string
description: Display name of the AI model
example: GPT-4 Turbo
modelFriendlyName:
type: string
description: Friendly display name of the selected model
example: GPT-4 Turbo
chatMode:
type: string
enum:
- web_search
- internal_search
description: |
Chat mode affecting response behavior.
example: internal_search
timezone:
type: string
minLength: 1
description: |
IANA timezone identifier from the client (top-level field).
Used to provide time-aware context to the AI.
example: America/New_York
currentTime:
type: string
format: date-time
description: |
ISO 8601 / RFC 3339 datetime from the client (top-level field; UTC `Z` or numeric offset).
example: '2026-04-12T16:00:00+05:30'
tools:
type: array
items:
type: string
minLength: 1
description: |
Optional list of tool identifiers (fully-qualified action names such as
"jira.create_issue") that the AI agent is permitted to invoke for this
request. When omitted the agent may use any configured tool. Applicable
only when chatMode is an agent mode (e.g. "agent:auto").
example:
- jira.create_issue
- confluence.search_content
AgentStreamCreateConversationRequest:
type: object
additionalProperties: false
description: |
Request body for `POST /agents/{agentKey}/conversations/stream`. Only
`query` is required; all other fields are optional overrides or routing
hints. Unknown fields are stripped during validation.
required:
- query
properties:
query:
type: string
minLength: 1
maxLength: 100000
description: |
User prompt for the first turn. Saved as the initial `user_query`
message and sent to the agent backend.
recordIds:
type: array
items:
type: string
format: objectId
description: |
Optional record ids to include as context for this turn. Each id
must be a 24-character MongoDB ObjectId.
filters:
allOf:
- $ref: '#/components/schemas/Filters'
description: |
Optional retrieval scope (`apps` / `kb`) for this turn. Each id must
be a UUID or a `knowledgeBase_` collection id. Omit for
agent defaults; send `{ "apps": [], "kb": [] }` to force no
knowledge sources for this turn.
appliedFilters:
allOf:
- $ref: '#/components/schemas/AppliedFilters'
description: |
UI filter state persisted on the saved user message. Not used for
retrieval and not forwarded to the upstream agent backend.
attachments:
type: array
items:
$ref: '#/components/schemas/ChatAttachmentRef'
description: |
Uploaded attachments to ground this turn. Each entry references a
record id returned from the agent attachment upload endpoint.
chatMode:
type: string
enum:
- auto
- quick
- verification
- deep
description: |
Chat mode hint forwarded to the agent backend.
- `auto` lets the agent pick its default strategy.
- `quick` favors low-latency answers over depth.
- `verification` runs additional grounding/verification passes.
- `deep` performs deeper retrieval and reasoning.
modelKey:
type: string
minLength: 1
description: |
AI model configuration id for this turn. Omit to use the agent's
default model.
modelName:
type: string
minLength: 1
description: Provider model name (the underlying LLM identifier).
modelFriendlyName:
type: string
minLength: 1
description: Friendly UI label for the selected model.
timezone:
type: string
minLength: 1
description: |
Client IANA timezone, such as `America/New_York`. Helps the agent
resolve relative date references in the prompt.
currentTime:
type: string
format: date-time
description: |
Client time in ISO 8601 / RFC 3339 format (UTC `Z` or numeric
offset). Sent alongside `timezone` for time-aware answers.
tools:
type: array
items:
type: string
minLength: 1
description: |
Allowed tool ids for this turn, such as `jira.create_issue`. Omit
to let the agent use its default toolset; send `[]` to disable
tools for this turn.
example:
query: what are some latest tech news?
modelKey: 5c1832f4-fa19-4167-b913-307fad3a6551
modelName: gpt-5.4-mini
modelFriendlyName: GPT 5.4 mini
chatMode: auto
timezone: Asia/Kolkata
currentTime: '2026-05-19T12:58:01+05:30'
tools: []
filters:
apps:
- 2605c882-61d4-4aa2-b480-a68c957c151d
- ed6d6cc4-70bd-4838-9aeb-488e910c833a
- aeab9ddc-fb9b-47c8-ad98-bd4744e19555
kb:
- 8747da12-4724-4a95-ac92-827b88d79647
appliedFilters:
apps:
- id: 2605c882-61d4-4aa2-b480-a68c957c151d
name: US Headlines, abcnews
nodeType: app
connector: RSS
- id: ed6d6cc4-70bd-4838-9aeb-488e910c833a
name: ABC News RSS
nodeType: app
connector: RSS
- id: aeab9ddc-fb9b-47c8-ad98-bd4744e19555
name: Hacker news rss
nodeType: app
connector: RSS
kb:
- id: 8747da12-4724-4a95-ac92-827b88d79647
name: Siddhant Ota's Private
nodeType: recordGroup
connector: KB
RegenerateRequest:
type: object
additionalProperties: false
description: |
Request body for regenerating an AI response. All fields are optional;
when omitted the model selection and execution context from the
original message are reused.
Supported fields:
- `filters` — optional `{ apps?, kb? }` filter object
- `chatMode` — optional non-empty chat mode string
- `modelKey`, `modelName`, `modelFriendlyName` —
optional non-empty model override fields
- `timezone` — optional non-empty client timezone string
- `currentTime` — optional ISO 8601 / RFC 3339 datetime string with
UTC `Z` or a numeric offset
- `tools` — optional array of non-empty tool identifiers
properties:
filters:
$ref: '#/components/schemas/Filters'
modelKey:
type: string
minLength: 1
description: |
Identifier of the AI model configuration to use for regeneration.
Typically a UUID returned by the model-management endpoints. When
omitted, the model used for the original message is reused.
example: 05438a37-68f2-4641-a8dc-6c47e63278ca
modelName:
type: string
minLength: 1
description: Provider model name (e.g. the underlying LLM identifier).
example: gpt-5.4-mini
modelFriendlyName:
type: string
minLength: 1
description: Friendly display name of the selected model.
example: mini
chatMode:
type: string
minLength: 1
description: |
Chat mode used for regeneration (for example `internal_search`,
`web_search`, or an agent mode such as `agent:auto`).
example: internal_search
timezone:
type: string
minLength: 1
description: |
IANA timezone identifier from the client. Used to provide
time-aware context to the AI during regeneration.
example: Asia/Calcutta
currentTime:
type: string
format: date-time
description: |
ISO 8601 / RFC 3339 datetime from the client (UTC `Z` or numeric
offset). Used to anchor any relative time references in the query.
example: '2026-05-11T15:43:21+05:30'
tools:
type: array
items:
type: string
minLength: 1
description: |
Optional list of tool identifiers (fully-qualified action names
such as `jira.create_issue`) the agent may invoke when
regenerating. Applicable only in agent chat modes.
example:
- jira.create_issue
- confluence.search_content
AddMessageRequest:
type: object
description: Request body for adding a message to an existing conversation
required:
- query
properties:
query:
type: string
minLength: 1
description: The follow-up question or message content
example: Can you elaborate on the revenue trends?
filters:
$ref: '#/components/schemas/Filters'
appliedFilters:
$ref: '#/components/schemas/AppliedFilters'
attachments:
type: array
items:
$ref: '#/components/schemas/ChatAttachmentRef'
description: |
Uploaded chat attachments for this follow-up turn (see
`POST /conversations/attachments/upload`).
modelKey:
type: string
description: Override the model for this specific message
modelName:
type: string
description: Display name of the model
modelFriendlyName:
type: string
description: Friendly display name of the model
chatMode:
type: string
enum:
- web_search
- internal_search
description: Chat mode for this message
timezone:
type: string
minLength: 1
description: |
IANA timezone identifier from the client (top-level field).
Used to provide time-aware context to the AI.
example: America/New_York
currentTime:
type: string
format: date-time
description: |
ISO 8601 / RFC 3339 datetime from the client (top-level field; UTC `Z` or numeric offset).
example: '2026-04-12T16:00:00+05:30'
tools:
type: array
items:
type: string
minLength: 1
description: |
Optional list of tool identifiers the agent may invoke for this
follow-up message. Semantics are identical to the create-conversation
tools field.
example:
- jira.create_issue
- confluence.search_content
AgentAddMessageStreamRequest:
type: object
additionalProperties: false
description: |
Request body for `POST /agents/{agentKey}/conversations/{conversationId}/messages/stream`.
Only `query` is required; all other fields are optional overrides or
routing hints. Unknown fields are stripped during validation.
required:
- query
properties:
query:
type: string
minLength: 1
description: |
User follow-up prompt to append to the existing agent conversation.
Saved as a new `user_query` message before the upstream AI stream
starts.
filters:
allOf:
- $ref: '#/components/schemas/Filters'
description: |
Optional retrieval scope (`apps` / `kb`) for this turn. Each id must
be a UUID or a `knowledgeBase_` collection id. Omit to let
the agent use its stored defaults; send `{ "apps": [], "kb": [] }`
to force no knowledge sources for this turn.
appliedFilters:
allOf:
- $ref: '#/components/schemas/AppliedFilters'
description: |
UI filter state persisted on the saved user message. Not used for
retrieval and not forwarded to the upstream agent backend.
attachments:
type: array
items:
$ref: '#/components/schemas/ChatAttachmentRef'
description: |
Uploaded attachments to ground this turn. Each entry references a
record id returned from the agent attachment upload endpoint.
chatMode:
type: string
enum:
- auto
- quick
- verification
- deep
description: |
Chat mode hint forwarded to the agent backend. Defaults to `auto`
in the upstream AI payload when omitted.
- `auto` lets the agent pick its default strategy.
- `quick` favors low-latency answers over depth.
- `verification` runs additional grounding/verification passes.
- `deep` performs deeper retrieval and reasoning.
modelKey:
type: string
minLength: 1
description: |
AI model configuration id override for this turn. Omit to use the
agent's default model.
modelName:
type: string
minLength: 1
description: Provider model name (the underlying LLM identifier).
modelFriendlyName:
type: string
minLength: 1
description: Friendly UI label for the selected model.
timezone:
type: string
minLength: 1
description: |
Client IANA timezone, such as `America/New_York`. Helps the agent
resolve relative date references in the prompt.
currentTime:
type: string
format: date-time
description: |
Client time in ISO 8601 / RFC 3339 format (UTC `Z` or numeric
offset). Sent alongside `timezone` for time-aware answers.
tools:
type: array
items:
type: string
minLength: 1
description: |
Allowed tool ids for this turn, such as `jira.create_issue`. Omit
to let the agent use its default toolset; send `[]` to disable
tools for this turn.
example:
query: can you elaborate on the latest headlines?
modelKey: 5c1832f4-fa19-4167-b913-307fad3a6551
modelName: gpt-5.4-mini
modelFriendlyName: GPT 5.4 mini
chatMode: verification
timezone: Asia/Kolkata
currentTime: '2026-05-19T12:58:01+05:30'
tools: []
filters:
apps:
- 2605c882-61d4-4aa2-b480-a68c957c151d
- ed6d6cc4-70bd-4838-9aeb-488e910c833a
kb:
- 8747da12-4724-4a95-ac92-827b88d79647
appliedFilters:
apps:
- id: 2605c882-61d4-4aa2-b480-a68c957c151d
name: US Headlines, abcnews
nodeType: app
connector: RSS
- id: ed6d6cc4-70bd-4838-9aeb-488e910c833a
name: ABC News RSS
nodeType: app
connector: RSS
kb:
- id: 8747da12-4724-4a95-ac92-827b88d79647
name: Siddhant Ota's Private
nodeType: recordGroup
connector: KB
Message:
type: object
additionalProperties: false
description: |
A single message within a conversation. Messages can be user queries,
AI responses, system messages, or error notifications.
properties:
_id:
type: string
format: objectId
description: Unique message identifier
messageType:
type: string
enum:
- user_query
- bot_response
- error
- feedback
- system
description: |
Type of message:
- `user_query` - User's question or input
- `bot_response` - AI-generated response
- `error` - Error message from the system
- `feedback` - User feedback on a response
- `system` - System notification or status
content:
type: string
description: The message text content
contentFormat:
type: string
enum:
- MARKDOWN
- JSON
- HTML
description: Format of the content for rendering
default: MARKDOWN
citations:
type: array
items:
$ref: '#/components/schemas/CitationReference'
description: References to source documents used in the response
confidence:
type: string
nullable: true
description: |
AI confidence in the answer. Present only on `bot_response` messages,
and only when the model emitted a trailing confidence block.
This field is now optional and nullable; it was previously always present and non-nullable. Treat a missing or `null` value as "no confidence reported" and guard before using it. Change effective in SDK v1.3.0 (v1.2.0 and earlier always populated it).
followUpQuestions:
type: array
items:
$ref: '#/components/schemas/FollowUpQuestion'
description: Suggested follow-up questions
feedback:
type: array
items:
$ref: '#/components/schemas/MessageFeedback'
description: User feedback on this message
metadata:
type: object
additionalProperties: false
properties:
processingTimeMs:
type: number
description: Time taken to generate response in milliseconds
modelVersion:
type: string
description: Version of the AI model used
aiTransactionId:
type: string
description: Transaction ID for tracking in AI backend
reason:
type: string
description: Additional context or reasoning
modelInfo:
$ref: '#/components/schemas/ConversationModelInfo'
appliedFilters:
$ref: '#/components/schemas/AppliedFilters'
referenceData:
type: array
description: |
Reference identifiers extracted from tool responses, used to scope
follow-up queries (for example Jira project keys or record IDs).
items:
type: object
additionalProperties: false
properties:
name:
type: string
description: Display name shown to the user.
id:
type: string
description: Technical identifier (numeric ID, UUID, etc.).
type:
type: string
description: Item type (e.g. `project`, `issue`, `file`, `notebook`, `page`).
app:
type: string
description: |
Source application (e.g. `jira`, `confluence`, `sharepoint`,
`slack`, `drive`, `gmail`).
webUrl:
type: string
description: URL to open the item in a browser.
metadata:
type: object
additionalProperties:
type: string
description: |
App-specific fields keyed by name (e.g. `key` for a Jira project,
`siteId` for a SharePoint document).
attachments:
type: array
description: |
Files uploaded for this message turn (see
`POST /conversations/attachments/upload`).
items:
$ref: '#/components/schemas/ChatAttachmentRef'
tools:
type: array
description: Tool call results invoked during this message turn.
items:
type: object
additionalProperties: false
properties:
toolName:
type: string
toolResult: {}
createdAt:
type: string
format: date-time
updatedAt:
type: string
format: date-time
CitationReference:
type: object
additionalProperties: false
description: Reference to a source document cited in a response
properties:
citationId:
type: string
format: objectId
description: ID of the citation record
relevanceScore:
type: number
minimum: 0
maximum: 1
description: How relevant this citation is to the query (0-1)
excerpt:
type: string
description: Relevant excerpt from the source document
context:
type: string
description: Additional context around the citation
Citation:
type: object
additionalProperties: false
description: |
A populated citation document. Represents a single chunk of source
content (e.g. a passage from a document or record) referenced by an
AI response, together with its provenance metadata.
required:
- _id
- content
- chunkIndex
- citationType
- metadata
- createdAt
- updatedAt
properties:
_id:
type: string
format: objectId
content:
type: string
description: The cited text chunk
chunkIndex:
type: integer
description: Index of this chunk within the source record
citationType:
type: string
description: Source type identifier (e.g. `vectordb|document`)
metadata:
$ref: '#/components/schemas/PersistedSemanticSearchCitationMetadata'
createdAt:
type: string
format: date-time
updatedAt:
type: string
format: date-time
ConversationModelInfo:
type: object
additionalProperties: false
description: AI model configuration recorded against a conversation or message.
properties:
modelKey:
type: string
description: Stable identifier of the configured model record
modelName:
type: string
description: Provider-facing model name (e.g. `gpt-4o-mini`)
modelProvider:
type: string
description: Provider key (e.g. `openai`, `anthropic`)
modelFriendlyName:
type: string
description: Human-readable display name
chatMode:
type: string
description: Chat mode used for this turn (e.g. `quick`, `internal_search`)
FollowUpQuestion:
type: object
additionalProperties: false
description: AI-suggested follow-up question
properties:
question:
type: string
description: The suggested question text
confidence:
type: string
description: Confidence level for this suggestion
reasoning:
type: string
description: Why this question might be relevant
MessageFeedbackSubmitRequest:
type: object
additionalProperties: false
description: |
Gateway request body for submitting message feedback (Zod
`feedbackBodySchema`). All fields are optional; an empty object is
accepted. Matches the first-party chat UI payload shape.
properties:
isHelpful:
type: boolean
description: Overall helpfulness signal (thumbs up/down).
categories:
type: array
description: Issue or positive categories that apply to the response.
items:
type: string
enum:
- incorrect_information
- missing_information
- irrelevant_information
- unclear_explanation
- poor_citations
- excellent_answer
- helpful_citations
- well_explained
- other
comments:
type: object
additionalProperties: false
description: Free-text comments grouped by sentiment.
properties:
positive:
type: string
description: What was good about the response.
negative:
type: string
description: What could be improved.
MessageFeedback:
type: object
additionalProperties: false
description: |
Comprehensive feedback on an AI response. Feedback helps improve
the AI's performance and response quality over time.
properties:
isHelpful:
type: boolean
description: Overall helpfulness rating
ratings:
type: object
additionalProperties: false
properties:
accuracy:
type: integer
minimum: 1
maximum: 5
description: How accurate was the information (1-5)
relevance:
type: integer
minimum: 1
maximum: 5
description: How relevant was the response (1-5)
completeness:
type: integer
minimum: 1
maximum: 5
description: How complete was the answer (1-5)
clarity:
type: integer
minimum: 1
maximum: 5
description: How clear was the explanation (1-5)
categories:
type: array
items:
type: string
enum:
- incorrect_information
- missing_information
- irrelevant_information
- unclear_explanation
- poor_citations
- excellent_answer
- helpful_citations
- well_explained
- other
description: Categories of issues or positive attributes identified
comments:
type: object
additionalProperties: false
properties:
positive:
type: string
description: What was good about the response
negative:
type: string
description: What could be improved
suggestions:
type: string
description: Specific suggestions for improvement
citationFeedback:
type: array
items:
type: object
additionalProperties: false
properties:
_id:
type: string
format: objectId
description: Auto-generated sub-document identifier
citationId:
type: string
format: objectId
isRelevant:
type: boolean
relevanceScore:
type: integer
minimum: 1
maximum: 5
comment:
type: string
description: Feedback on individual citations
followUpQuestionsHelpful:
type: boolean
description: Were the suggested follow-up questions helpful
unusedFollowUpQuestions:
type: array
items:
type: string
description: Follow-up questions that were suggested but not used by the user
source:
type: string
enum:
- user
- system
- admin
- auto
default: user
description: Origin of the feedback. Always present in responses (server applies the default `user`).
feedbackProvider:
type: string
format: objectId
description: User who submitted the feedback
timestamp:
type: integer
format: int64
description: |
Time the feedback was created, stored as a Number (epoch milliseconds)
with a server-side default of `Date.now`, so always present in responses.
Not an ISO 8601 datetime.
revisions:
type: array
description: Audit trail of edits to this feedback entry
items:
type: object
additionalProperties: false
properties:
_id:
type: string
format: objectId
description: Auto-generated sub-document identifier
updatedFields:
type: array
items:
type: string
description: Names of feedback fields modified in this revision
previousValues:
type: object
additionalProperties: true
description: |
Map of previously-set values for the fields named in `updatedFields`,
keyed by field name. Stored as a Mongoose Map of Mixed values.
updatedBy:
type: string
format: objectId
updatedAt:
type: integer
format: int64
description: Time the revision was recorded, as epoch milliseconds.
metrics:
type: object
additionalProperties: false
description: Optional telemetry captured alongside the feedback
properties:
timeToFeedback:
type: number
description: Time from response delivery to feedback submission
userInteractionTime:
type: number
description: Total time the user spent reviewing the response
feedbackSessionId:
type: string
userAgent:
type: string
platform:
type: string
MessageFeedbackAppendMetrics:
type: object
additionalProperties: false
required:
- timeToFeedback
description: |
Telemetry recorded server-side alongside the feedback. Always present
on append responses.
properties:
timeToFeedback:
type: number
description: |
Milliseconds between message creation and feedback submission.
Always present.
userAgent:
type: string
description: Value of the `User-Agent` request header captured server-side.
MessageFeedbackAppendEntry:
type: object
additionalProperties: false
required:
- feedbackProvider
- timestamp
- metrics
description: |
The feedback entry just appended to the message. Echoes the fields
supplied in the request plus server-stamped `feedbackProvider`,
`timestamp`, and `metrics`.
properties:
isHelpful:
type: boolean
description: Echoed from the request when supplied.
categories:
type: array
description: Echoed categories from the request.
items:
type: string
enum:
- incorrect_information
- missing_information
- irrelevant_information
- unclear_explanation
- poor_citations
- excellent_answer
- helpful_citations
- well_explained
- other
comments:
type: object
additionalProperties: false
description: Echoed free-text comments from the request.
properties:
positive:
type: string
negative:
type: string
feedbackProvider:
type: string
format: objectId
description: User who submitted the feedback. Always present.
timestamp:
type: integer
format: int64
description: |
Submission time as epoch milliseconds (not an ISO 8601 datetime).
Always present.
metrics:
$ref: '#/components/schemas/MessageFeedbackAppendMetrics'
MessageFeedbackUpdateResponse:
type: object
additionalProperties: false
required:
- conversationId
- messageId
- feedback
- meta
description: |
Gateway response after appending feedback to a bot-response message.
properties:
conversationId:
type: string
format: objectId
description: Conversation the feedback was attached to.
messageId:
type: string
format: objectId
description: Message the feedback was attached to.
feedback:
$ref: '#/components/schemas/MessageFeedbackAppendEntry'
meta:
type: object
additionalProperties: false
required:
- requestId
- timestamp
- duration
properties:
requestId:
type: string
description: |
Server-side request identifier. Read from the `X-Request-ID`
header when supplied, otherwise auto-generated, so this field
is always present.
timestamp:
type: string
format: date-time
duration:
type: integer
description: Server-side processing time in milliseconds.
Conversation:
type: object
description: |
A conversation represents a chat session between a user and the AI.
Conversations maintain context across multiple messages and can be
shared, archived, and organized.
properties:
_id:
type: string
format: objectId
description: Unique conversation identifier
userId:
type: string
format: objectId
description: ID of the user who owns this conversation
orgId:
type: string
format: objectId
description: Organization this conversation belongs to
title:
type: string
description: |
Conversation title, auto-generated from first query
or manually updated
example: Q4 Financial Report Discussion
initiator:
type: string
format: objectId
description: User who started the conversation
messages:
type: array
items:
$ref: '#/components/schemas/Message'
description: All messages in this conversation
status:
type: string
enum:
- None
- Inprogress
- Complete
- Failed
description: |
Current status of the conversation:
- `None` — no activity yet
- `Inprogress` — AI is processing
- `Complete` — response ready
- `Failed` — error occurred
failReason:
type: string
description: Error description, populated only when `status` is `Failed`.
modelInfo:
type: object
properties:
modelKey:
type: string
modelName:
type: string
modelFriendlyName:
type: string
description: Friendly display name of the selected model
modelProvider:
type: string
chatMode:
type: string
description: AI model configuration used
isShared:
type: boolean
default: false
description: Whether this conversation is shared with others
shareLink:
type: string
description: Shareable link if conversation is shared
sharedWith:
type: array
items:
type: object
properties:
userId:
type: string
format: objectId
accessLevel:
type: string
enum:
- read
- write
description: Users this conversation is shared with
isArchived:
type: boolean
default: false
description: Whether this conversation is archived
archivedBy:
type: string
format: objectId
nullable: true
description: |
User ID of the last user who archived this row, or `null` after
unarchive cleared the archive state. Absent on rows that have
never been archived.
isDeleted:
type: boolean
default: false
description: Whether this conversation has been soft-deleted.
deletedBy:
type: string
format: objectId
description: User who soft-deleted this conversation.
conversationErrors:
type: array
description: Errors recorded against this conversation (e.g. failed message generations).
items:
type: object
required:
- message
properties:
message:
type: string
errorType:
type: string
timestamp:
type: string
format: date-time
messageId:
type: string
format: objectId
stack:
type: string
metadata:
type: object
additionalProperties: true
metadata:
type: object
additionalProperties: true
description: Free-form metadata attached to the conversation.
lastActivityAt:
type: integer
description: Unix timestamp of last activity
createdAt:
type: string
format: date-time
updatedAt:
type: string
format: date-time
isOwner:
type: boolean
description: |
Computed per request. `true` when the requesting user is the
conversation's `initiator`.
readOnly: true
accessLevel:
type: string
enum:
- read
- write
description: |
Computed per request. The requester's effective access level:
their entry in `sharedWith`, or `read` by default.
readOnly: true
ConversationListItem:
type: object
description: |
Conversation summary returned by list endpoints. Identical to
`Conversation` but omits `messages` to keep list payloads small.
Fetch a single conversation to retrieve its messages.
properties:
_id:
type: string
format: objectId
userId:
type: string
format: objectId
orgId:
type: string
format: objectId
title:
type: string
initiator:
type: string
format: objectId
status:
type: string
enum:
- None
- Inprogress
- Complete
- Failed
failReason:
type: string
modelInfo:
type: object
properties:
modelKey:
type: string
modelName:
type: string
modelFriendlyName:
type: string
modelProvider:
type: string
chatMode:
type: string
isShared:
type: boolean
shareLink:
type: string
sharedWith:
type: array
items:
type: object
properties:
userId:
type: string
format: objectId
accessLevel:
type: string
enum:
- read
- write
isArchived:
type: boolean
archivedBy:
type: string
format: objectId
nullable: true
description: |
User ID of the last user who archived this row, or `null` after
unarchive cleared the archive state. Absent on rows that have
never been archived.
isDeleted:
type: boolean
deletedBy:
type: string
format: objectId
conversationErrors:
type: array
items:
type: object
properties:
message:
type: string
errorType:
type: string
timestamp:
type: string
format: date-time
messageId:
type: string
format: objectId
stack:
type: string
metadata:
type: object
additionalProperties: true
metadata:
type: object
additionalProperties: true
lastActivityAt:
type: integer
createdAt:
type: string
format: date-time
updatedAt:
type: string
format: date-time
isOwner:
type: boolean
readOnly: true
accessLevel:
type: string
enum:
- read
- write
readOnly: true
SemanticSearchRequest:
type: object
description: |
Request body for performing semantic search across the enterprise knowledge base.
**How Semantic Search Works:**
1. Query is converted to vector embeddings
2. Similar content is found using vector similarity
3. Results are ranked by relevance score
4. Matching chunks with metadata are returned
**Filtering:**
Use filters to narrow search scope to specific apps or knowledge bases.
required:
- query
properties:
query:
type: string
minLength: 1
description: |
Natural language search query. The system understands
semantic meaning, not just keywords.
example: employee onboarding procedures
filters:
$ref: '#/components/schemas/Filters'
limit:
type: integer
minimum: 1
maximum: 100
default: 10
description: Maximum number of results to return
SemanticSearchBoundingBox:
type: object
additionalProperties: false
description: Normalized bounding region for a chunk (when available).
properties:
x:
type: number
y:
type: number
SemanticSearchHitMetadata:
type: object
additionalProperties: false
description: |
Per-hit metadata after retrieval enrichment (record + vector context).
Listed fields are the documented contract; Qdrant or pipeline updates may add more keys over time—extend this schema when new stable fields appear.
properties:
orgId:
type: string
nullable: true
recordId:
type: string
nullable: true
virtualRecordId:
type: string
nullable: true
recordName:
type: string
nullable: true
recordType:
type: string
nullable: true
recordVersion:
nullable: true
oneOf:
- type: string
- type: number
origin:
type: string
nullable: true
connector:
type: string
nullable: true
connectorId:
type: string
nullable: true
connectorName:
type: string
nullable: true
blockText:
type: string
nullable: true
blockType:
type: string
nullable: true
description: |
Block type for this hit. Common values: `text`, `image`, `table_row`, `table`,
`record_summary` (whole-record semantic summary chunk — no block index).
bounding_box:
type: array
nullable: true
items:
$ref: '#/components/schemas/SemanticSearchBoundingBox'
pageNum:
type: array
nullable: true
items:
nullable: true
type: integer
extension:
type: string
nullable: true
mimeType:
type: string
nullable: true
blockNum:
type: array
nullable: true
items:
type: number
chunkIndex:
type: integer
nullable: true
sheetName:
type: string
nullable: true
sheetNum:
type: integer
nullable: true
webUrl:
type: string
nullable: true
previewRenderable:
type: boolean
nullable: true
hideWeburl:
type: boolean
nullable: true
categories:
type: array
nullable: true
items:
type: string
departments:
type: array
nullable: true
items:
type: string
topics:
type: array
nullable: true
items:
type: string
languages:
type: array
nullable: true
items:
type: string
subcategoryLevel1:
type: string
nullable: true
subcategoryLevel2:
type: string
nullable: true
subcategoryLevel3:
type: string
nullable: true
score:
type: number
nullable: true
_id:
type: string
nullable: true
_collection_name:
type: string
nullable: true
blockIndex:
type: integer
nullable: true
blockId:
type: string
nullable: true
isBlock:
type: boolean
nullable: true
isBlockGroup:
type: boolean
nullable: true
isRecordSummary:
type: boolean
nullable: true
description: |
Set to `true` by the indexing pipeline when this vector chunk represents a
whole-record semantic summary rather than an individual block. When true,
`blockIndex` is absent and `block_type` on the parent hit is `record_summary`.
kbId:
type: string
nullable: true
description: Knowledge base id merged from graph record during retrieval (when present).
point_id:
description: Qdrant point identifier attached during vector lookup (shape varies by deployment).
nullable: true
oneOf:
- type: string
- type: integer
- type: number
SemanticSearchHit:
type: object
additionalProperties: false
description: |
One search hit returned by the retrieval service. Most hits use string `content`;
table or grouped blocks may serialize structured payloads as JSON arrays.
Listed fields are the documented contract; extend this schema when new stable top-level keys are introduced.
properties:
score:
type: number
nullable: true
citationType:
type: string
nullable: true
chunkIndex:
type: integer
nullable: true
metadata:
$ref: '#/components/schemas/SemanticSearchHitMetadata'
content:
type: string
nullable: true
virtual_record_id:
type: string
nullable: true
block_type:
type: string
nullable: true
description: |
Block type for this hit. Common values: `text`, `image`, `table_row`, `table`,
`record_summary` (whole-record semantic summary — `block_index` is `null` for these hits).
block_index:
type: integer
nullable: true
SemanticSearchGraphRecord:
type: object
description: |
Graph record vertex returned in `records` and as values of `virtual_to_record_map`.
All listed fields are optional in the schema so partial or evolving documents validate; typical Arango documents
usually include `_key`, `_id`, `_rev`, `orgId`, `recordName`, `externalRecordId`, `recordType`, `origin`,
`createdAtTimestamp`, and `connectorId`. Extend this schema when new stable fields appear on Record vertices.
properties:
_key:
type: string
nullable: true
_id:
type: string
nullable: true
_rev:
type: string
nullable: true
recordName:
type: string
nullable: true
externalRecordId:
type: string
nullable: true
recordType:
type: string
nullable: true
origin:
type: string
nullable: true
createdAtTimestamp:
type: number
nullable: true
connectorId:
type: string
nullable: true
orgId:
type: string
nullable: true
updatedAtTimestamp:
type: number
nullable: true
externalGroupId:
type: string
nullable: true
externalParentId:
type: string
nullable: true
externalRevisionId:
type: string
nullable: true
externalRootGroupId:
type: string
nullable: true
recordGroupId:
type: string
nullable: true
version:
type: number
nullable: true
connectorName:
type: string
nullable: true
mimeType:
type: string
nullable: true
webUrl:
type: string
nullable: true
lastSyncTimestamp:
type: number
nullable: true
sourceCreatedAtTimestamp:
type: number
nullable: true
sourceLastModifiedTimestamp:
type: number
nullable: true
isDeleted:
type: boolean
nullable: true
isArchived:
type: boolean
nullable: true
isVLMOcrProcessed:
type: boolean
nullable: true
deletedByUserId:
type: string
nullable: true
indexingStatus:
type: string
nullable: true
extractionStatus:
type: string
nullable: true
isLatestVersion:
type: boolean
nullable: true
isDirty:
type: boolean
nullable: true
reason:
type: string
nullable: true
lastIndexTimestamp:
type: number
nullable: true
lastExtractionTimestamp:
type: number
nullable: true
summaryDocumentId:
type: string
nullable: true
virtualRecordId:
type: string
nullable: true
previewRenderable:
type: boolean
nullable: true
isShared:
type: boolean
nullable: true
isDependentNode:
type: boolean
nullable: true
parentNodeId:
type: string
nullable: true
hideWeburl:
type: boolean
nullable: true
isInternal:
type: boolean
nullable: true
md5Checksum:
type: string
nullable: true
sizeInBytes:
type: number
nullable: true
definition:
type: string
nullable: true
sourceTables:
type: array
nullable: true
items:
type: string
rowCount:
type: number
nullable: true
SemanticSearchAppliedFilters:
type: object
additionalProperties: false
description: Present when KB filters were applied to the search request.
required:
- kb
- kb_count
properties:
kb:
type: array
items:
type: string
kb_count:
type: integer
SemanticSearchAiResponse:
type: object
additionalProperties: false
description: |
Payload returned by the AI retrieval service for a semantic search (embedded in `searchResponse`).
Optional `virtual_to_record_map` maps each virtual record id (string key) to one resolved graph record document.
Empty responses from the retrieval layer omit `virtual_to_record_map`; success payloads may include it alongside hits and records.
required:
- searchResults
- records
- status
- status_code
- message
properties:
searchResults:
type: array
items:
$ref: '#/components/schemas/SemanticSearchHit'
records:
type: array
items:
$ref: '#/components/schemas/SemanticSearchGraphRecord'
status:
type: string
status_code:
type: integer
message:
type: string
appliedFilters:
$ref: '#/components/schemas/SemanticSearchAppliedFilters'
virtual_to_record_map:
type: object
description: Maps virtual record id (object property name) to the accessible graph record document for that id.
additionalProperties:
$ref: '#/components/schemas/SemanticSearchGraphRecord'
SemanticSearchExecuteResponse:
type: object
additionalProperties: false
description: |
Immediate POST `/search` response: persisted search id plus the raw retrieval payload.
SDK-oriented modeling: named fields only at this level; dynamic-key maps inside `searchResponse` use
`additionalProperties` with a `$ref` (e.g. `virtual_to_record_map`) rather than boolean `additionalProperties: true`,
so generated clients retain typed values where possible.
required:
- searchId
- searchResponse
properties:
searchId:
type: string
format: objectId
searchResponse:
$ref: '#/components/schemas/SemanticSearchAiResponse'
PersistedSemanticSearchBoundingBox:
type: object
additionalProperties: false
description: |
Bounding box subdocument embedded in persisted citation metadata.
`boundingBoxSchema` does not set `_id: false`, so Mongoose auto-injects an `_id`.
required:
- _id
- x
- y
properties:
_id:
type: string
format: objectId
x:
type: number
y:
type: number
PersistedSemanticSearchCitationMetadata:
type: object
additionalProperties: false
description: |
Citation metadata as persisted in MongoDB. Required fields mirror the
Mongoose schema's `required: true` flags; the rest are optional and
may come through as `null` because the AI retrieval service emits
explicit nulls for absent fields.
required:
- orgId
- mimeType
- recordId
- recordName
- origin
properties:
orgId:
type: string
mimeType:
type: string
recordId:
type: string
recordName:
type: string
origin:
type: string
recordVersion:
type: integer
nullable: true
extension:
type: string
nullable: true
webUrl:
type: string
nullable: true
previewRenderable:
type: boolean
nullable: true
hideWeburl:
type: boolean
nullable: true
connector:
type: string
nullable: true
recordType:
type: string
nullable: true
blockNum:
type: array
nullable: true
items:
type: number
nullable: true
pageNum:
type: array
nullable: true
items:
type: number
nullable: true
sheetNum:
type: number
nullable: true
sheetName:
type: string
nullable: true
bounding_box:
type: array
nullable: true
items:
$ref: '#/components/schemas/PersistedSemanticSearchBoundingBox'
blockType:
type: string
nullable: true
description: |
Block type for this citation. Common values: `text`, `image`, `table_row`, `table`,
`record_summary` (whole-record semantic summary chunk).
blockText:
type: string
nullable: true
departments:
type: array
nullable: true
items:
type: string
languages:
type: array
nullable: true
items:
type: string
topics:
type: array
nullable: true
items:
type: string
PersistedSemanticSearchCitation:
type: object
additionalProperties: false
description: |
Populated citation document referenced from a persisted search.
The controller strips `__v` via `populate({ select: '-__v' })`.
required:
- _id
- content
- chunkIndex
- citationType
- metadata
- createdAt
- updatedAt
properties:
_id:
type: string
format: objectId
content:
type: string
chunkIndex:
type: integer
citationType:
type: string
metadata:
$ref: '#/components/schemas/PersistedSemanticSearchCitationMetadata'
createdAt:
type: string
format: date-time
updatedAt:
type: string
format: date-time
PersistedSemanticSearchSharedWithEntry:
type: object
additionalProperties: false
description: |
Entry inside `sharedWith[]`. The schema sets `_id: false` on these
sub-docs, so no auto-injected `_id` is present.
required:
- userId
- accessLevel
properties:
userId:
type: string
format: objectId
accessLevel:
type: string
enum:
- read
- write
PersistedSemanticSearch:
type: object
additionalProperties: false
description: |
Persisted search document as returned to clients.
`records` is a string-valued map: each value is `JSON.stringify()`,
keyed by the source record's `_id` or `_key`. Clients must `JSON.parse`
each value to recover the underlying record object (whose shape resembles
`SemanticSearchGraphRecord`). This intentionally differs from the
`searchResponse.records` array on the POST `/search` response, which is
passed through from the retrieval service untouched.
required:
- _id
- __v
- query
- limit
- orgId
- userId
- citationIds
- records
- isShared
- sharedWith
- isArchived
- createdAt
- updatedAt
properties:
_id:
type: string
format: objectId
__v:
type: integer
query:
type: string
limit:
type: integer
orgId:
type: string
format: objectId
userId:
type: string
format: objectId
citationIds:
type: array
items:
$ref: '#/components/schemas/PersistedSemanticSearchCitation'
records:
type: object
description: |
Map of source-record id (or `_key`) to a JSON-stringified record object.
Clients must `JSON.parse` each value before reading fields.
additionalProperties:
type: string
isShared:
type: boolean
shareLink:
type: string
description: Set once the search has been shared via `/search/{searchId}/share`.
sharedWith:
type: array
items:
$ref: '#/components/schemas/PersistedSemanticSearchSharedWithEntry'
isArchived:
type: boolean
archivedBy:
type: string
format: objectId
nullable: true
description: |
User ID of the last user who archived this row, or `null` after
an unarchive cleared the archive state. Absent on rows that have
never been archived. Currently-archived rows cannot reach this
endpoint because `buildFilter` enforces `isArchived: false`.
createdAt:
type: string
format: date-time
updatedAt:
type: string
format: date-time
PersistedSemanticSearchEnvelope:
type: array
description: |
GET `/search/{searchId}` calls `Model.find()` (not `findOne()`) and sends
the result as-is, so the wire format is an array of zero or one
persisted search docs. A non-existent id returns `200 []`, **not** `404`.
items:
$ref: '#/components/schemas/PersistedSemanticSearch'
SemanticSearchHistoryItem:
type: object
additionalProperties: false
description: |
One persisted search row as returned by `GET /search`. Mirrors the
persisted search document except `citationIds` is an array of
ObjectId strings (citations are not populated on the list endpoint,
unlike `GET /search/{searchId}`).
`shareLink` is absent from the JSON when the search has not been
shared. `archivedBy` is `null` on rows that were previously archived
and then unarchived, and absent on rows that have never been
archived. The list endpoint already filters out currently-archived
rows, so a string user-id value never appears here in practice.
required:
- _id
- __v
- query
- limit
- orgId
- userId
- citationIds
- records
- isShared
- sharedWith
- isArchived
- createdAt
- updatedAt
properties:
_id:
type: string
format: objectId
__v:
type: integer
query:
type: string
limit:
type: integer
orgId:
type: string
format: objectId
userId:
type: string
format: objectId
citationIds:
type: array
items:
type: string
format: objectId
records:
type: object
description: |
Map of source-record id (or `_key`) to `JSON.stringify()`.
Clients must `JSON.parse` each value to recover the underlying
record object. Populated at write-time in the POST `/search` handler.
additionalProperties:
type: string
isShared:
type: boolean
shareLink:
type: string
description: Set once the search has been shared via `/search/{searchId}/share`.
sharedWith:
type: array
items:
$ref: '#/components/schemas/PersistedSemanticSearchSharedWithEntry'
isArchived:
type: boolean
archivedBy:
type: string
format: objectId
nullable: true
description: |
User ID of the last user who archived this row, or `null` after
an unarchive cleared the archive state. Absent on rows that have
never been archived.
createdAt:
type: string
format: date-time
updatedAt:
type: string
format: date-time
SemanticSearchHistoryPagination:
type: object
additionalProperties: false
description: |
Pagination block emitted by `buildPaginationMetadata` (utils.ts:417).
`totalPages` is `Math.ceil(totalCount / limit)`, so an empty result
has `totalPages: 0`, not `1`.
required:
- page
- limit
- totalCount
- totalPages
- hasNextPage
- hasPrevPage
properties:
page:
type: integer
limit:
type: integer
totalCount:
type: integer
totalPages:
type: integer
hasNextPage:
type: boolean
hasPrevPage:
type: boolean
SemanticSearchHistoryAppliedDateRange:
type: object
additionalProperties: false
description: |
Echoed back only when the caller passed `startDate` and/or `endDate`.
Each bound is an ISO 8601 string when set; the field is absent when
the corresponding query param was omitted (utils.ts:480-486 reads
`appliedFilters.createdAt.$gte?.toISOString()` directly, so missing
bounds become `undefined` and drop out of the JSON).
properties:
start:
type: string
format: date-time
end:
type: string
format: date-time
SemanticSearchHistoryFiltersApplied:
type: object
additionalProperties: false
description: |
Echo of which filters the caller actually supplied, built by
`buildFiltersMetadata` (utils.ts:430-486). `page` and `limit` always
appear because they are normalised to defaults before being recorded,
so `filters` is never empty and `values` always contains at least
`{ page, limit }`. Other keys appear only when the matching query
param was non-empty (or, for `dateRange`, when `createdAt` was set
on the Mongo filter).
`values` keys are scalar strings rather than typed primitives
(`'true'`/`'false'`, `'5'`, etc.) because they are passed through
from `req.query` as Express parsed them — only `page` and `limit`
are coerced to integers via `safeParsePagination`.
required:
- filters
- values
properties:
filters:
type: array
items:
type: string
enum:
- page
- limit
- search
- shared
- tags
- minMessages
- sortBy
- sortOrder
- startDate
- endDate
- messageType
- dateRange
values:
type: object
additionalProperties: false
properties:
page:
type: integer
limit:
type: integer
search:
type: string
shared:
type: string
tags:
type: string
minMessages:
type: string
sortBy:
type: string
sortOrder:
type: string
startDate:
type: string
endDate:
type: string
messageType:
type: string
dateRange:
$ref: '#/components/schemas/SemanticSearchHistoryAppliedDateRange'
SemanticSearchHistoryFilterToggle:
type: object
additionalProperties: false
description: |
Generic "filter X is available, current value is Y" block used for
`shared`, `tags`, `minMessages`, `search`, and `messageType`. Either
`type` (free-form value) or `values` (enum of allowed strings) is
present, not both. `current` is the caller-supplied value passed
through from `req.query`, hence string-or-null even when `type` is
`'number'`.
required:
- description
- current
- applied
properties:
type:
type: string
values:
type: array
items:
type: string
description:
type: string
current:
type: string
nullable: true
applied:
type: boolean
SemanticSearchHistoryPaginationField:
type: object
additionalProperties: false
required:
- type
- current
- min
- max
- default
- description
- applied
properties:
type:
type: string
current:
type: integer
min:
type: integer
max:
type: integer
default:
type: integer
description:
type: string
applied:
type: boolean
SemanticSearchHistorySortField:
type: object
additionalProperties: false
description: |
Used for `available.sorting.{sortBy,sortOrder}` and
`available.sortingMessages.{sortBy,sortOrder}`. The `applied` flag
is present on `sorting.*` and absent on `sortingMessages.*`, so it
is optional here.
required:
- values
- default
- description
- current
properties:
values:
type: array
items:
type: string
default:
type: string
description:
type: string
current:
type: string
applied:
type: boolean
SemanticSearchHistoryDateRange:
type: object
additionalProperties: false
required:
- type
- description
- format
- current
- applied
properties:
type:
type: string
description:
type: string
format:
type: string
current:
type: object
additionalProperties: false
required:
- start
- end
properties:
start:
type: string
nullable: true
end:
type: string
nullable: true
applied:
type: boolean
SemanticSearchHistoryFiltersAvailable:
type: object
additionalProperties: false
description: |
Catalogue of filters the endpoint supports, plus their current values
and `applied` flags. Built by `buildFiltersMetadata` (utils.ts:430-624).
required:
- shared
- tags
- minMessages
- search
- pagination
- sorting
- dateFilters
- messageFilters
- sortingMessages
properties:
shared:
$ref: '#/components/schemas/SemanticSearchHistoryFilterToggle'
tags:
$ref: '#/components/schemas/SemanticSearchHistoryFilterToggle'
minMessages:
$ref: '#/components/schemas/SemanticSearchHistoryFilterToggle'
search:
$ref: '#/components/schemas/SemanticSearchHistoryFilterToggle'
pagination:
type: object
additionalProperties: false
required:
- page
- limit
properties:
page:
$ref: '#/components/schemas/SemanticSearchHistoryPaginationField'
limit:
$ref: '#/components/schemas/SemanticSearchHistoryPaginationField'
sorting:
type: object
additionalProperties: false
required:
- sortBy
- sortOrder
properties:
sortBy:
$ref: '#/components/schemas/SemanticSearchHistorySortField'
sortOrder:
$ref: '#/components/schemas/SemanticSearchHistorySortField'
dateFilters:
type: object
additionalProperties: false
required:
- dateRange
properties:
dateRange:
$ref: '#/components/schemas/SemanticSearchHistoryDateRange'
messageFilters:
type: object
additionalProperties: false
required:
- messageType
properties:
messageType:
$ref: '#/components/schemas/SemanticSearchHistoryFilterToggle'
sortingMessages:
type: object
additionalProperties: false
required:
- sortBy
- sortOrder
properties:
sortBy:
$ref: '#/components/schemas/SemanticSearchHistorySortField'
sortOrder:
$ref: '#/components/schemas/SemanticSearchHistorySortField'
SemanticSearchHistoryFilters:
type: object
additionalProperties: false
required:
- applied
- available
properties:
applied:
$ref: '#/components/schemas/SemanticSearchHistoryFiltersApplied'
available:
$ref: '#/components/schemas/SemanticSearchHistoryFiltersAvailable'
SemanticSearchHistoryMeta:
type: object
additionalProperties: false
description: |
`requestId` comes from `req.context?.requestId` and is omitted from
the JSON when upstream middleware did not set it.
required:
- timestamp
- duration
properties:
requestId:
type: string
timestamp:
type: string
format: date-time
duration:
type: integer
SemanticSearchHistoryResponse:
type: object
additionalProperties: false
description: |
Envelope returned by `GET /search`. The handler runs `find()` plus
`countDocuments()` in parallel and assembles `{ searchHistory,
pagination, filters, meta }` (es_controller.ts:3925-3973).
required:
- searchHistory
- pagination
- filters
- meta
properties:
searchHistory:
type: array
items:
$ref: '#/components/schemas/SemanticSearchHistoryItem'
pagination:
$ref: '#/components/schemas/SemanticSearchHistoryPagination'
filters:
$ref: '#/components/schemas/SemanticSearchHistoryFilters'
meta:
$ref: '#/components/schemas/SemanticSearchHistoryMeta'
AgentKnowledgeFiltersParsed:
type: object
additionalProperties: false
description: |
Indexed scope for a knowledge connector: record-group ids (collections /
KB roots) and individual record ids. First-party create/update flows set
`recordGroups` and `records`. On GET, `filtersParsed` is this shape
parsed from the stored `filters` JSON string.
properties:
recordGroups:
type: array
items:
type: string
description: Record-group ids (e.g. knowledge-base roots) in scope.
records:
type: array
items:
type: string
description: Individual record ids in scope.
Toolset:
type: object
additionalProperties: false
description: |
Toolset instance linked to an agent, as projected by the graph store on
`GET /agents/{agentKey}` and `GET /agents`. Multiple instances of the
same integration type are distinguished by `instanceId` and optional
`instanceName`.
properties:
_key:
type: string
description: Toolset instance node key in the backing graph store.
name:
allOf:
- $ref: '#/components/schemas/AgentCreateToolsetName'
description: Integration / toolset type key.
displayName:
type: string
description: Human-readable toolset product label (for example `Jira` or `Slack`).
type:
type: string
instanceId:
type: string
description: Admin-created toolset instance id
instanceName:
type: string
description: Human-readable instance label (e.g. sidebar instance name)
selectedTools:
type: array
nullable: true
description: |
Tool names explicitly selected for this toolset instance, when the
instance was created with a subset selection. `null`/absent when the
instance exposes all of the toolset's tools.
items:
type: string
tools:
type: array
items:
type: object
additionalProperties: false
properties:
_key:
type: string
description: Tool node key in the backing graph store.
name:
type: string
fullName:
type: string
toolsetName:
type: string
description: Toolset type key the tool belongs to.
description:
type: string
deprecated:
type: boolean
readOnly: true
description: |
Server-stamped on `GET /agents/{agentKey}`: `true` when the
tool's `fullName` is no longer in the runtime tool registry
(its `@tool` was removed). Read-only; ignored on create/update
bodies. Not stamped on the `GET /agents` list projection.
AgentFilters:
description: |
Knowledge scope filter as stored on the graph edge. The Node `getAgent`
handler proxies this field unchanged from the AI service (only `agent.id`
is stripped). May be a JSON string (typical graph storage) or an object.
Prefer `filtersParsed` on GET for a guaranteed parsed object with the
same keys as the object branch below.
oneOf:
- $ref: '#/components/schemas/AgentKnowledgeFiltersParsed'
- type: string
description: JSON-encoded filter object (graph storage format).
Knowledge:
type: object
additionalProperties: false
description: |
Knowledge connector / indexed scope linked to an agent, as projected by
the graph store on `GET /agents/{agentKey}` and `GET /agents`.
properties:
_key:
type: string
connectorId:
type: string
name:
type: string
type:
type: string
displayName:
type: string
filters:
$ref: '#/components/schemas/AgentFilters'
filtersParsed:
readOnly: true
description: |
Server-derived read-only object parsed from the stored
`filters` JSON by the graph provider on GET (Neo4j / Arango).
Empty object when `filters` is missing or invalid JSON.
allOf:
- $ref: '#/components/schemas/AgentKnowledgeFiltersParsed'
Agent:
type: object
additionalProperties: false
description: |
Detailed agent projection returned by agent detail-style endpoints such
as `GET /agents/{agentKey}`.
properties:
_id:
type: string
description: Full document id in the backing graph store.
example: agentInstances/e6f848ca-e2ab-4594-9925-e1136629f474
_key:
type: string
description: Stable agent key used in route params.
example: e6f848ca-e2ab-4594-9925-e1136629f474
_rev:
type: string
description: Backend document revision token.
example: _lkNlcOm---
name:
type: string
description: Display name of the agent
example: Customer Support Assistant
description:
type: string
description: What this agent is designed to do
systemPrompt:
type: string
description: System instructions that define agent behavior
createdBy:
type: string
format: objectId
description: MongoDB user ID of the agent creator
startMessage:
type: string
description: Initial greeting shown when a conversation with this agent starts
instructions:
type: string
nullable: true
description: Additional agent execution instructions
models:
type: array
description: |
Configured model entries for this agent.
example:
- modelType: llm
provider: azureOpenAI
modelName: gpt-5.4-mini
modelKey: f3a4b5b6-5b6c-4e85-9097-3202cfe696fc
isMultimodal: true
isReasoning: true
isDefault: true
modelFriendlyName: GPT 5.4 mini
items:
oneOf:
- type: string
- type: object
additionalProperties: false
properties:
modelKey:
type: string
modelName:
type: string
provider:
type: string
isReasoning:
type: boolean
isMultimodal:
type: boolean
isDefault:
type: boolean
modelType:
type: string
description: |
Model category. Must be `llm` for agent model entries (same
value as `ModelType` for LLMs; string only — enum is not used here).
example: llm
modelFriendlyName:
type: string
toolsets:
type: array
description: |
Toolset instances linked to the agent (GET /agents/{agentKey} graph projection).
Multiple instances of the same integration type are distinguished by `instanceId`
and optional `instanceName`.
items:
$ref: '#/components/schemas/Toolset'
knowledge:
type: array
description: Knowledge connectors and indexed scopes linked to the agent
items:
$ref: '#/components/schemas/Knowledge'
shareWithOrg:
type: boolean
description: Whether the agent is shared with the whole organization
webSearch:
type: object
additionalProperties: false
nullable: true
description: Web search provider attached to this agent. Null when none is configured.
properties:
provider:
type: string
description: Provider identifier (e.g. "tavily", "serper", "exa", "duckduckgo")
providerKey:
type: string
providerLabel:
type: string
required:
- provider
example:
provider: serper
tags:
type: array
items:
type: string
description: Free-form agent tags.
createdAtTimestamp:
type: integer
format: int64
description: Unix epoch timestamp in milliseconds when the agent was created.
updatedAtTimestamp:
type: integer
format: int64
description: Unix epoch timestamp in milliseconds when the agent was last updated.
updatedBy:
type: string
nullable: true
description: User id of the last updater, if present.
isActive:
type: boolean
description: Whether the agent is active.
isDeleted:
type: boolean
description: Whether the agent has been soft-deleted.
isServiceAccount:
type: boolean
description: Whether this agent is a service-account agent.
access_type:
type: string
description: How the user can access this agent.
example: INDIVIDUAL
user_role:
type: string
description: Effective role of the current user on this agent.
example: OWNER
can_view:
type: boolean
description: Effective permission to view the agent.
can_share:
type: boolean
description: Effective permission to share the agent.
can_edit:
type: boolean
description: Effective permission to edit the agent.
can_delete:
type: boolean
description: Effective permission to delete the agent.
required:
- _id
- _key
- createdAtTimestamp
- createdBy
- isActive
- isDeleted
- isServiceAccount
- models
- name
- tags
- updatedAtTimestamp
- shareWithOrg
- knowledge
- toolsets
- can_view
- can_share
- can_edit
- can_delete
- user_role
- access_type
AgentListItem:
type: object
additionalProperties: false
description: |
Agent projection returned by `GET /agents`.
This is the list-view envelope item emitted by the Python backend and
forwarded by the Node gateway. It is not the full detail projection
used by `GET /agents/{agentKey}`.
properties:
_id:
type: string
description: Full document id in the backing graph store.
example: agentInstances/e6f848ca-e2ab-4594-9925-e1136629f474
_key:
type: string
description: Stable agent key used in route params.
example: e6f848ca-e2ab-4594-9925-e1136629f474
_rev:
type: string
description: Backend document revision token.
example: _lkNlcOm---
createdAtTimestamp:
type: integer
format: int64
description: Unix epoch timestamp in milliseconds when the agent was created.
createdBy:
type: string
description: MongoDB user ID of the agent creator
description:
type: string
nullable: true
description: Short human-readable description of the agent.
instructions:
type: string
nullable: true
description: Additional execution instructions stored on the agent.
isActive:
type: boolean
description: Whether the agent is active.
isDeleted:
type: boolean
description: Whether the agent has been soft-deleted.
isServiceAccount:
type: boolean
description: Whether this agent is a service-account agent.
models:
type: array
description: |
Model entries configured on the agent.
For `GET /agents`, the backend returns the stored normalized string
representation, typically `modelKey_modelName`.
items:
type: string
name:
type: string
description: Display name of the agent.
startMessage:
type: string
nullable: true
description: Greeting shown at conversation start.
systemPrompt:
type: string
nullable: true
description: System prompt stored on the agent.
tags:
type: array
items:
type: string
description: Free-form agent tags.
updatedAtTimestamp:
type: integer
format: int64
description: Unix epoch timestamp in milliseconds when the agent was last updated.
updatedBy:
type: string
nullable: true
description: User id of the last updater, if present.
webSearch:
type: object
additionalProperties: false
nullable: true
description: |
Web-search provider attachment for this agent, or `null` when none is attached.
For `GET /agents`, the response formatter always emits `provider`.
It may also emit `providerKey` and `providerLabel` when those values
were present on the stored attachment. It does not emit `iconPath`
on this response path.
properties:
provider:
type: string
providerKey:
type: string
providerLabel:
type: string
shareWithOrg:
type: boolean
description: Whether the agent is shared with the organization.
toolsets:
type: array
description: |
Toolset instances linked to the agent. Same projection as
`GET /agents/{agentKey}`; the backend builds it from the graph edges
for each agent on the returned page.
items:
$ref: '#/components/schemas/Toolset'
knowledge:
type: array
description: |
Knowledge connectors and indexed scopes linked to the agent. Same
projection as `GET /agents/{agentKey}`; the backend builds it from
the graph edges for each agent on the returned page.
items:
$ref: '#/components/schemas/Knowledge'
can_view:
type: boolean
description: Effective permission to view the agent.
can_share:
type: boolean
description: Effective permission to share the agent.
can_edit:
type: boolean
description: Effective permission to edit the agent.
can_delete:
type: boolean
description: Effective permission to delete the agent.
user_role:
type: string
description: Effective role of the current user on this agent.
example: OWNER
access_type:
type: string
description: How the user can access this agent.
example: INDIVIDUAL
required:
- _id
- _key
- createdAtTimestamp
- createdBy
- isActive
- isDeleted
- isServiceAccount
- models
- name
- tags
- updatedAtTimestamp
- shareWithOrg
- toolsets
- knowledge
- can_view
- can_share
- can_edit
- can_delete
- user_role
- access_type
AgentListPagination:
type: object
additionalProperties: false
description: Pagination block returned by `GET /agents`.
required:
- currentPage
- limit
- totalItems
- totalPages
- hasNext
- hasPrev
properties:
currentPage:
type: integer
description: Current 1-based page number.
example: 1
limit:
type: integer
description: Page size actually applied by the backend.
example: 20
totalItems:
type: integer
description: Total number of matching agents across all pages.
example: 2
totalPages:
type: integer
description: Total number of pages for the current query.
example: 1
hasNext:
type: boolean
description: Whether a later page exists.
example: false
hasPrev:
type: boolean
description: Whether an earlier page exists.
example: false
AgentListResponse:
type: object
additionalProperties: false
description: |
Paginated response returned by `GET /agents`.
The Node gateway forwards the Python backend response on success. If
the backend returns a non-200 response, the gateway still returns HTTP
200 with `success: true`, an empty `agents` array, and a zeroed
pagination block derived from the requested `page` / `limit`.
required:
- success
- agents
- pagination
properties:
success:
type: boolean
example: true
agents:
type: array
items:
$ref: '#/components/schemas/AgentListItem'
pagination:
$ref: '#/components/schemas/AgentListPagination'
GetAgentResponse:
type: object
additionalProperties: false
description: |
Success envelope returned by `GET /agents/{agentKey}`.
The Node gateway forwards the backend response as an envelope with a
top-level status/message and the detailed agent projection nested under
`agent`.
required:
- status
- message
- agent
properties:
status:
type: string
example: success
message:
type: string
example: Agent retrieved successfully
agent:
$ref: '#/components/schemas/Agent'
AgentCreateModelEntry:
description: |
Accepted model entry for `POST /agents/create`.
The gateway accepts either a non-empty string model entry or an object entry
with a required `modelKey`.
The `models` array must include at least one object entry with `isReasoning: true`.
String-only entries are schema-valid but are rejected at the gateway with HTTP 400.
oneOf:
- type: string
minLength: 1
- type: object
additionalProperties: false
required:
- modelKey
properties:
modelKey:
type: string
minLength: 1
modelName:
type: string
provider:
type: string
isReasoning:
type: boolean
AgentCreateToolRef:
type: object
additionalProperties: false
required:
- name
properties:
name:
type: string
fullName:
type: string
description:
type: string
maxLength: 10000
AgentCreateToolsetName:
type: string
description: Registered toolset name (lowercase) accepted by the create-agent gateway.
enum:
- calendar
- clickup
- confluence
- drive
- github
- gmail
- jira
- lumos
- mariadb
- onedrive
- outlook
- redshift
- salesforce
- sharepoint
- slack
- teams
- zoom
AgentCreateToolset:
type: object
additionalProperties: false
required:
- name
properties:
name:
$ref: '#/components/schemas/AgentCreateToolsetName'
displayName:
type: string
maxLength: 200
type:
type: string
maxLength: 100
instanceId:
type: string
maxLength: 256
instanceName:
type: string
maxLength: 200
tools:
type: array
items:
$ref: '#/components/schemas/AgentCreateToolRef'
AgentCreateKnowledge:
type: object
additionalProperties: false
required:
- connectorId
properties:
connectorId:
type: string
filters:
oneOf:
- $ref: '#/components/schemas/AgentKnowledgeFiltersParsed'
- type: string
- type: array
items: {}
AgentCreateWebSearch:
description: |
Accepted web-search attachment for `POST /agents/create`.
The gateway accepts either a provider string or an object with at least
a `provider` field.
anyOf:
- type: string
- type: object
additionalProperties: false
properties:
provider:
type: string
providerKey:
type: string
maxLength: 256
providerLabel:
type: string
maxLength: 200
iconPath:
type: string
maxLength: 500
required:
- provider
- type: 'null'
AgentCreateRequest:
type: object
additionalProperties: false
required:
- name
- models
properties:
name:
type: string
minLength: 1
maxLength: 200
description: Agent display name
example: Product Support Agent
description:
type: string
maxLength: 100000
description: What the agent does
startMessage:
type: string
maxLength: 100000
description: Initial greeting shown when conversation starts
systemPrompt:
type: string
maxLength: 100000
description: System instructions for the agent
instructions:
type: string
maxLength: 100000
description: Additional agent execution instructions
models:
type: array
minItems: 1
description: |
Agent model configuration entries. The gateway requires at least one
object entry with `isReasoning: true`. String-only arrays are schema-valid
but rejected at runtime with HTTP 400.
items:
$ref: '#/components/schemas/AgentCreateModelEntry'
tags:
type: array
maxItems: 50
items:
type: string
maxLength: 100
shareWithOrg:
type: boolean
default: false
description: Share agent with the organization
isServiceAccount:
type: boolean
default: false
description: Create the agent as a service-account agent
toolsets:
type: array
maxItems: 100
description: Toolsets attached to the agent (instance-aware)
items:
$ref: '#/components/schemas/AgentCreateToolset'
knowledge:
type: array
maxItems: 100
description: Knowledge sources connected to the agent
items:
$ref: '#/components/schemas/AgentCreateKnowledge'
webSearch:
$ref: '#/components/schemas/AgentCreateWebSearch'
AgentCreateWarning:
type: object
additionalProperties: false
properties:
name:
type: string
error:
type: string
AgentCreateResponseTool:
type: object
additionalProperties: false
required:
- name
- fullName
- key
properties:
name:
type: string
fullName:
type: string
key:
type: string
AgentCreateResponseToolset:
type: object
additionalProperties: false
required:
- name
- displayName
- key
- tools
properties:
name:
$ref: '#/components/schemas/AgentCreateToolsetName'
displayName:
type: string
description: Human-readable toolset product label (for example `Jira` or `Slack`).
key:
type: string
tools:
type: array
items:
$ref: '#/components/schemas/AgentCreateResponseTool'
AgentCreateResponseKnowledge:
type: object
additionalProperties: false
required:
- connectorId
- key
- filters
properties:
connectorId:
type: string
key:
type: string
filters:
oneOf:
- type: object
additionalProperties: true
- type: string
- type: array
items: {}
AgentCreateResponseAgent:
type: object
additionalProperties: false
required:
- _key
- name
- description
- startMessage
- systemPrompt
- instructions
- models
- tags
- webSearch
- isActive
- isServiceAccount
- createdBy
- updatedBy
- createdAtTimestamp
- updatedAtTimestamp
- isDeleted
- toolsets
- knowledge
properties:
_key:
type: string
name:
type: string
description:
type: string
startMessage:
type: string
systemPrompt:
type: string
instructions:
type: string
nullable: true
models:
type: array
items:
type: string
tags:
type: array
items:
type: string
webSearch:
anyOf:
- type: object
additionalProperties: false
properties:
provider:
type: string
providerKey:
type: string
providerLabel:
type: string
- type: 'null'
isActive:
type: boolean
isServiceAccount:
type: boolean
createdBy:
type: string
updatedBy:
type: string
nullable: true
createdAtTimestamp:
type: integer
updatedAtTimestamp:
type: integer
isDeleted:
type: boolean
toolsets:
type: array
items:
$ref: '#/components/schemas/AgentCreateResponseToolset'
knowledge:
type: array
items:
$ref: '#/components/schemas/AgentCreateResponseKnowledge'
AgentCreateResponse:
type: object
additionalProperties: false
required:
- status
- message
- agent
properties:
status:
type: string
enum:
- success
- partial_success
message:
type: string
agent:
$ref: '#/components/schemas/AgentCreateResponseAgent'
warnings:
anyOf:
- type: array
items:
$ref: '#/components/schemas/AgentCreateWarning'
- type: 'null'
AgentUpdateRequest:
type: object
additionalProperties: false
description: |
Partial update payload for `PUT /agents/{agentKey}`.
Every field is optional — only the fields present in the request body
are updated. When `models` is included, the gateway Zod middleware
(mirroring the Python backend) requires at least one model entry and
at least one object entry with `isReasoning: true`.
properties:
name:
type: string
minLength: 1
maxLength: 200
description: Agent display name
example: Renamed Agent
description:
type: string
maxLength: 100000
description: What the agent does
startMessage:
type: string
maxLength: 100000
description: Initial greeting shown when conversation starts
systemPrompt:
type: string
maxLength: 100000
description: System instructions for the agent
instructions:
type: string
maxLength: 100000
description: Additional agent execution instructions
models:
type: array
minItems: 1
description: |
Agent model configuration entries. When present, the Zod middleware
requires at least one object entry with `isReasoning: true`.
String-only arrays are schema-valid but rejected at runtime with HTTP 400.
items:
$ref: '#/components/schemas/AgentCreateModelEntry'
tags:
type: array
maxItems: 50
items:
type: string
maxLength: 100
shareWithOrg:
type: boolean
default: false
description: Share agent with the organization
isServiceAccount:
type: boolean
default: false
description: Mark agent as a service account
toolsets:
type: array
maxItems: 100
description: Toolsets attached to the agent (instance-aware)
items:
$ref: '#/components/schemas/AgentCreateToolset'
knowledge:
type: array
maxItems: 100
description: Knowledge sources connected to the agent
items:
$ref: '#/components/schemas/AgentCreateKnowledge'
webSearch:
$ref: '#/components/schemas/AgentCreateWebSearch'
AgentUpdateResponse:
type: object
additionalProperties: false
required:
- status
- message
properties:
status:
type: string
enum:
- success
message:
type: string
example: Agent updated successfully
AgentDeleteResponse:
type: object
additionalProperties: false
required:
- status
- message
- deleted
properties:
status:
type: string
enum:
- success
message:
type: string
example: Agent deleted successfully
deleted:
type: object
additionalProperties: false
required:
- agents
- toolsets
- tools
- knowledge
- edges
properties:
agents:
type: integer
minimum: 0
example: 1
toolsets:
type: integer
minimum: 0
example: 0
tools:
type: integer
minimum: 0
example: 0
knowledge:
type: integer
minimum: 0
example: 0
edges:
type: integer
minimum: 0
example: 0
AgentConversationListItem:
type: object
additionalProperties: false
description: |
Conversation summary returned by `GET /agents/{agentKey}/conversations`.
The handler excludes `messages` and `__v` from both result sets. Rows
in `sharedWithMeConversations` also omit `sharedWith` because the
secondary query explicitly deselects that field before serialization.
properties:
_id:
type: string
format: objectId
agentKey:
type: string
description: Agent identifier from the route path
userId:
type: string
format: objectId
orgId:
type: string
format: objectId
title:
type: string
initiator:
type: string
format: objectId
status:
type: string
enum:
- None
- Inprogress
- Complete
- Failed
failReason:
type: string
modelInfo:
$ref: '#/components/schemas/ConversationModelInfo'
isShared:
type: boolean
shareLink:
type: string
sharedWith:
type: array
items:
type: object
additionalProperties: false
properties:
userId:
type: string
format: objectId
accessLevel:
type: string
enum:
- read
- write
isArchived:
type: boolean
archivedBy:
type: string
format: objectId
nullable: true
archivedAt:
type: string
format: date-time
description: |
Present on archived conversation endpoints. Derived from the
document `updatedAt` timestamp when the archive response is built.
isDeleted:
type: boolean
deletedBy:
type: string
format: objectId
nullable: true
conversationErrors:
type: array
items:
type: object
additionalProperties: false
properties:
message:
type: string
errorType:
type: string
timestamp:
type: string
format: date-time
messageId:
type: string
format: objectId
stack:
type: string
metadata:
type: object
additionalProperties: true
conversationSource:
type: string
enum:
- agent_chat
lastActivityAt:
type: integer
format: int64
description: Epoch milliseconds of the latest activity on the thread
createdAt:
type: string
format: date-time
updatedAt:
type: string
format: date-time
isOwner:
type: boolean
readOnly: true
description: |
Computed per request. `true` when the conversation `initiator`
matches the authenticated user.
accessLevel:
type: string
enum:
- read
- write
readOnly: true
description: |
Computed per request from `sharedWith`; defaults to `read` when no
explicit share grant is attached to the serialized row.
AgentConversationListResponse:
type: object
additionalProperties: false
description: |
Envelope returned by `GET /agents/{agentKey}/conversations`.
`conversations` contains rows owned by the caller for the agent;
`sharedWithMeConversations` contains rows shared with the caller for
the same agent. Both arrays use the same pagination and sort inputs,
but `pagination.totalCount` and `totalPages` are computed only from
`conversations` because the handler counts the owned-query filter only.
required:
- conversations
- sharedWithMeConversations
- pagination
- filters
- meta
properties:
conversations:
type: array
items:
$ref: '#/components/schemas/AgentConversationListItem'
sharedWithMeConversations:
type: array
items:
$ref: '#/components/schemas/AgentConversationListItem'
pagination:
$ref: '#/components/schemas/SemanticSearchHistoryPagination'
filters:
$ref: '#/components/schemas/SemanticSearchHistoryFilters'
meta:
$ref: '#/components/schemas/SemanticSearchHistoryMeta'
AgentArchivedConversationGroup:
type: object
additionalProperties: false
description: |
Archived conversations for a single agent, sliced to the first page
of the per-agent archive query (limit 5, sorted newest first).
required:
- agentKey
- conversations
- pagination
properties:
agentKey:
type: string
description: Agent identifier the conversations belong to.
conversations:
type: array
items:
$ref: '#/components/schemas/AgentConversationListItem'
pagination:
$ref: '#/components/schemas/SemanticSearchHistoryPagination'
AgentArchivedGroupsResponse:
type: object
additionalProperties: false
description: |
Response from `GET /agents/conversations/show/archives` — archived agent
conversations grouped by `agentKey`, with agent-level pagination over
the groups and a fixed slice of conversations under each agent.
required:
- groups
- agentPagination
- meta
properties:
groups:
type: array
items:
$ref: '#/components/schemas/AgentArchivedConversationGroup'
agentPagination:
$ref: '#/components/schemas/SemanticSearchHistoryPagination'
meta:
$ref: '#/components/schemas/RequestMeta'
AgentArchivedConversationSummary:
type: object
additionalProperties: false
description: |
Archive counts and bounds for the current result page returned by
`GET /agents/{agentKey}/conversations/show/archives`.
properties:
totalArchived:
type: integer
description: Total archived conversations matching the filter
oldestArchive:
type: string
format: date-time
description: Archive timestamp of the first item in the current page. Omitted when the page is empty.
newestArchive:
type: string
format: date-time
description: Archive timestamp of the last item in the current page. Omitted when the page is empty.
AgentArchivedConversationListResponse:
type: object
additionalProperties: false
description: |
Envelope returned by `GET /agents/{agentKey}/conversations/show/archives`.
required:
- conversations
- pagination
- filters
- summary
- meta
properties:
conversations:
type: array
items:
$ref: '#/components/schemas/AgentConversationListItem'
pagination:
$ref: '#/components/schemas/SemanticSearchHistoryPagination'
filters:
$ref: '#/components/schemas/SemanticSearchHistoryFilters'
summary:
$ref: '#/components/schemas/AgentArchivedConversationSummary'
meta:
$ref: '#/components/schemas/SemanticSearchHistoryMeta'
RequestMeta:
type: object
additionalProperties: false
description: Basic request metadata returned by the API.
required:
- timestamp
- duration
properties:
requestId:
type: string
timestamp:
type: string
format: date-time
duration:
type: integer
ConversationTitleUpdateRequest:
type: object
additionalProperties: false
required:
- title
properties:
title:
type: string
minLength: 1
maxLength: 200
description: New title for the conversation
example: ABC News Follow-up
StoredAgentConversation:
type: object
additionalProperties: false
description: |
Stored agent conversation document returned by non-list endpoints.
properties:
_id:
type: string
format: objectId
agentKey:
type: string
userId:
type: string
format: objectId
orgId:
type: string
format: objectId
title:
type: string
initiator:
type: string
format: objectId
messages:
type: array
items:
$ref: '#/components/schemas/Message'
status:
type: string
enum:
- None
- Inprogress
- Complete
- Failed
failReason:
type: string
modelInfo:
$ref: '#/components/schemas/ConversationModelInfo'
isShared:
type: boolean
shareLink:
type: string
sharedWith:
type: array
items:
type: object
additionalProperties: false
properties:
userId:
type: string
format: objectId
accessLevel:
type: string
enum:
- read
- write
isArchived:
type: boolean
archivedBy:
type: string
format: objectId
nullable: true
isDeleted:
type: boolean
deletedBy:
type: string
format: objectId
nullable: true
conversationErrors:
type: array
items:
type: object
additionalProperties: false
properties:
_id:
type: string
format: objectId
message:
type: string
errorType:
type: string
timestamp:
type: string
format: date-time
messageId:
type: string
format: objectId
stack:
type: string
metadata:
type: object
additionalProperties: true
conversationSource:
type: string
enum:
- agent_chat
lastActivityAt:
type: integer
format: int64
createdAt:
type: string
format: date-time
updatedAt:
type: string
format: date-time
__v:
type: integer
AgentConversationTitleUpdateResponse:
type: object
additionalProperties: false
required:
- conversation
- meta
properties:
conversation:
$ref: '#/components/schemas/StoredAgentConversation'
meta:
$ref: '#/components/schemas/RequestMeta'
AgentConversationDeleteResponse:
type: object
additionalProperties: false
description: |
Envelope returned by `DELETE /agents/{agentKey}/conversations/{conversationId}`.
When the conversation does not exist, belongs to a different agent, or
was already deleted, the API still returns HTTP 200 with
`conversation: null`.
required:
- message
- conversation
properties:
message:
type: string
enum:
- Conversation deleted successfully
conversation:
nullable: true
$ref: '#/components/schemas/StoredAgentConversation'
AgentConversationDetailMessageCitation:
type: object
additionalProperties: false
description: |
Citation entry returned inside a conversation message after the
handler populates `messages.citations.citationId` and rewrites each
item to `{ citationId, citationData }`.
properties:
citationId:
type: string
format: objectId
citationData:
$ref: '#/components/schemas/Citation'
AgentConversationDetailMessage:
type: object
additionalProperties: false
description: |
Message shape returned by `GET /agents/{agentKey}/conversations/{conversationId}`.
The response spreads the stored message document and replaces
`citations` with populated citation objects.
properties:
_id:
type: string
format: objectId
messageType:
type: string
enum:
- user_query
- bot_response
- error
- feedback
- system
content:
type: string
contentFormat:
type: string
enum:
- MARKDOWN
- JSON
- HTML
citations:
type: array
items:
$ref: '#/components/schemas/AgentConversationDetailMessageCitation'
confidence:
type: string
enum:
- Very High
- High
- Medium
- Low
- Unknown
nullable: true
description: |
AI confidence in the answer. Present only on `bot_response` messages,
and only when the model emitted a trailing confidence block.
This field is now optional and nullable; it was previously always present and non-nullable. Treat a missing or `null` value as "no confidence reported" and guard before using it. Change effective in SDK v1.3.0 (v1.2.0 and earlier always populated it).
followUpQuestions:
type: array
items:
$ref: '#/components/schemas/FollowUpQuestion'
feedback:
type: array
items:
$ref: '#/components/schemas/MessageFeedback'
referenceData:
type: array
description: |
Reference identifiers surfaced from tool responses, used to scope
follow-up queries.
items:
type: object
additionalProperties: false
properties:
name:
type: string
description: Display name shown to the user.
id:
type: string
description: Technical identifier (numeric ID, UUID, etc.).
type:
type: string
description: Item type (e.g. `project`, `issue`, `file`, `notebook`, `page`).
app:
type: string
description: |
Source application (e.g. `jira`, `confluence`, `sharepoint`,
`slack`, `drive`, `gmail`).
webUrl:
type: string
description: URL to open the item in a browser.
metadata:
type: object
additionalProperties:
type: string
description: |
App-specific fields keyed by name (e.g. `key` for a Jira project,
`siteId` for a SharePoint document).
attachments:
type: array
description: |
Files uploaded for this message turn (see
`POST /agents/{agentKey}/conversations/attachments/upload`).
items:
$ref: '#/components/schemas/ChatAttachmentRef'
tools:
type: array
description: Tool call results invoked during this message turn.
items:
type: object
additionalProperties: false
properties:
toolName:
type: string
toolResult: {}
modelInfo:
$ref: '#/components/schemas/ConversationModelInfo'
appliedFilters:
$ref: '#/components/schemas/AppliedFilters'
metadata:
type: object
additionalProperties: false
properties:
processingTimeMs:
type: number
modelVersion:
type: string
aiTransactionId:
type: string
createdAt:
type: string
format: date-time
updatedAt:
type: string
format: date-time
AgentConversationDetailPagination:
type: object
additionalProperties: false
description: |
Message pagination returned inside the `conversation` object. The
handler paginates backwards from the end of the stored message array,
then sorts the selected page in memory before serialization.
required:
- page
- limit
- totalCount
- totalPages
- hasNextPage
- hasPrevPage
- messageRange
properties:
page:
type: integer
limit:
type: integer
totalCount:
type: integer
totalPages:
type: integer
hasNextPage:
type: boolean
description: True when older messages exist outside the returned page
hasPrevPage:
type: boolean
description: True when newer messages exist outside the returned page
messageRange:
type: object
additionalProperties: false
required:
- start
- end
properties:
start:
type: integer
end:
type: integer
AgentConversationDetailAccess:
type: object
additionalProperties: false
properties:
isOwner:
type: boolean
accessLevel:
type: string
enum:
- read
- write
AgentConversationDetail:
type: object
additionalProperties: false
description: |
Reduced conversation view returned by the by-id GET route. This is
not the raw `AgentConversation` document shape: fields like `agentKey`,
`userId`, `orgId`, `conversationSource`, and root-level `messages`
metadata outside the selected slice are omitted.
required:
- id
- createdAt
- isShared
- sharedWith
- messages
- pagination
- access
properties:
id:
type: string
format: objectId
title:
type: string
initiator:
type: string
format: objectId
createdAt:
type: string
format: date-time
isShared:
type: boolean
sharedWith:
type: array
items:
type: object
additionalProperties: false
properties:
userId:
type: string
format: objectId
accessLevel:
type: string
enum:
- read
- write
status:
type: string
enum:
- None
- Inprogress
- Complete
- Failed
failReason:
type: string
messages:
type: array
items:
$ref: '#/components/schemas/AgentConversationDetailMessage'
modelInfo:
$ref: '#/components/schemas/ConversationModelInfo'
pagination:
$ref: '#/components/schemas/AgentConversationDetailPagination'
access:
$ref: '#/components/schemas/AgentConversationDetailAccess'
AgentConversationDetailMeta:
type: object
additionalProperties: false
description: |
Request-scoped metadata returned by the by-id GET route. `requestId`
is omitted when upstream middleware did not attach one.
required:
- timestamp
- duration
- conversationId
- messageCount
properties:
requestId:
type: string
timestamp:
type: string
format: date-time
duration:
type: integer
conversationId:
type: string
format: objectId
messageCount:
type: integer
AgentConversationDetailResponse:
type: object
additionalProperties: false
description: |
Envelope returned by `GET /agents/{agentKey}/conversations/{conversationId}`.
required:
- conversation
- filters
- meta
properties:
conversation:
$ref: '#/components/schemas/AgentConversationDetail'
filters:
$ref: '#/components/schemas/SemanticSearchHistoryFilters'
meta:
$ref: '#/components/schemas/AgentConversationDetailMeta'
AgentConversationArchiveMeta:
type: object
additionalProperties: false
description: |
Request-scoped metadata returned by the archive route. `requestId` is
omitted when upstream middleware did not attach one.
required:
- timestamp
- duration
properties:
requestId:
type: string
timestamp:
type: string
format: date-time
duration:
type: integer
AgentConversationArchiveResponse:
type: object
additionalProperties: false
description: |
Envelope returned by `POST /agents/{agentKey}/conversations/{conversationId}/archive`.
required:
- id
- status
- archivedBy
- archivedAt
- meta
properties:
id:
type: string
format: objectId
status:
type: string
enum:
- archived
archivedBy:
type: string
format: objectId
archivedAt:
type: string
format: date-time
meta:
$ref: '#/components/schemas/AgentConversationArchiveMeta'
AgentConversationUnarchiveMeta:
type: object
additionalProperties: false
description: |
Request-scoped metadata returned by the unarchive route. `requestId` is
omitted when upstream middleware did not attach one.
required:
- timestamp
- duration
properties:
requestId:
type: string
timestamp:
type: string
format: date-time
duration:
type: integer
AgentConversationUnarchiveResponse:
type: object
additionalProperties: false
description: |
Envelope returned by `POST /agents/{agentKey}/conversations/{conversationId}/unarchive`.
required:
- id
- status
- unarchivedBy
- unarchivedAt
- meta
properties:
id:
type: string
format: objectId
status:
type: string
enum:
- unarchived
unarchivedBy:
type: string
format: objectId
unarchivedAt:
type: string
format: date-time
meta:
$ref: '#/components/schemas/AgentConversationUnarchiveMeta'
AgentRegenerateSSEEvent:
type: object
additionalProperties: false
description: |
SSE event envelope for `POST /agents/{agentKey}/conversations/{conversationId}/message/{messageId}/regenerate`.
Stable events:
- `connected` confirms the stream is open.
- `complete` returns the updated conversation plus request metadata
after the regenerated bot response is persisted.
- `error` returns a failure message. Conversation lookup failures,
unauthorized conversation access, and regenerate rule failures such
as "not the last message" are reported here after the stream starts.
Other events are forwarded from the agent backend and should be
treated as informational updates.
properties:
event:
type: string
enum:
- connected
- status
- tool_calls
- tool_call
- tool_success
- tool_error
- tool_result
- tool_execution_complete
- answer_chunk
- restreaming
- metadata
- complete
- error
data:
type: string
description: JSON-encoded event payload. Shape depends on `event`.
SSEEvent:
type: object
description: |
Server-Sent Event envelope for streaming chat responses.
`data` is a JSON-encoded string whose shape depends on `event`.
Three events are emitted by the API layer and have stable shapes
documented on the streaming routes:
- `connected` — fired once on connection. Carries the newly created
`conversationId` and `title` so the client can link the stream to
a row before any tokens arrive.
- `complete` — fired once after the AI backend finishes. Carries the
full persisted `conversation` and a `meta` block with `requestId`,
`timestamp` and `duration`.
- `error` — fired when the stream fails. Carries an `error` message
and optional `details`. The conversation row is marked FAILED
before the stream closes.
All other events are forwarded verbatim from the AI backend; their
payloads are AI-backend defined and may evolve. Currently observed
names include `status`, `answer_chunk`, `tool_call`, `tool_calls`,
`tool_result`, `tool_success`, `tool_error`,
`tool_execution_complete`, `restreaming`, and `metadata`.
properties:
event:
type: string
enum:
- connected
- status
- answer_chunk
- tool_call
- tool_calls
- tool_result
- tool_success
- tool_error
- tool_execution_complete
- restreaming
- metadata
- complete
- error
data:
type: string
description: JSON-encoded event payload. Shape depends on `event`.
AssistantStreamSSEEvent:
type: object
description: |
Server-Sent Event envelope for non-agent assistant chat streams
(`internal_search` / `web_search` chat modes). `data` is a
JSON-encoded string whose shape depends on `event`.
Three events are emitted by the API layer with stable, server-defined
shapes:
- `connected` — `{ "message": string, "conversationId": string,
"title": string }`. Fired once on connection so the client can link
the stream to the new row before any tokens arrive.
- `complete` — `{ "conversation": Conversation,
"meta": { "requestId": string, "timestamp": string,
"duration": number } }`. Fired once after the AI backend finishes.
- `error` — `{ "error": string, "details"?: string }`. Fired when the
stream fails; the conversation row is marked FAILED before close.
The remaining events are forwarded from the Python query service.
Their payloads are AI-backend defined and may evolve:
- `status` — progress message describing the current pipeline stage
(for example `started`, `searching`, `processing`, `checking_tools`,
`generating_answer`, `transforming`).
- `answer_chunk` — incremental token batch with running `accumulated`
text and any new `citations`.
- `tool_calls` — the assistant requested one or more tool calls.
Carries the assistant message that triggered the tool round.
- `tool_call` — emitted once per individual tool invocation as it
starts. Payload includes `tool_name`, `tool_args`, and `call_id`.
- `tool_success` — a tool finished successfully. Payload includes
`tool_name`, `summary`, `call_id`, and any `record_info`.
- `tool_error` — a tool invocation failed. Payload includes
`tool_name`, `error`, and `call_id`.
- `restreaming` — the LLM is being restarted with new context, for
example before a citation-verification pass.
Clients should ignore unknown event names rather than treating them
as errors.
properties:
event:
type: string
enum:
- connected
- status
- answer_chunk
- tool_calls
- tool_call
- tool_success
- tool_error
- restreaming
- complete
- error
data:
type: string
description: JSON-encoded event payload. Shape depends on `event`.
AssistantMessageStreamSSEEvent:
type: object
description: |
Server-Sent Event envelope for non-agent assistant follow-up message
streams (`internal_search` / `web_search` chat modes) on an existing
conversation. `data` is a JSON-encoded string whose shape depends on
`event`.
Same event vocabulary as the conversation-creation stream — only the
`connected` and `complete` payloads differ because the conversation
already exists when this route is called.
Three events are emitted by the API layer with stable, server-defined
shapes:
- `connected` — `{ "message": string }`. Fired once on connection.
No `conversationId` or `title` is included because the caller
already passed the conversation ID in the URL.
- `complete` — `{ "conversation": Conversation, "recordsUsed": number,
"meta": { "requestId": string, "timestamp": string,
"duration": number, "recordsUsed": number } }`. Fired once after
the AI backend finishes. `recordsUsed` is the count of citations
attached to the new assistant message.
- `error` — `{ "error": string, "details"?: string }`. Fired when the
stream fails; the conversation row is marked FAILED before close.
The remaining events are forwarded from the Python query service.
Their payloads are AI-backend defined and may evolve:
- `status` — progress message describing the current pipeline stage
(for example `started`, `transforming`, `searching`, `processing`,
`checking_tools`, `generating_answer`). `transforming` is common on
this route because follow-up turns always have prior history to
rewrite the query against.
- `answer_chunk` — incremental token batch with running `accumulated`
text and any new `citations`.
- `tool_calls` — the assistant requested one or more tool calls.
Carries the assistant message that triggered the tool round.
- `tool_call` — emitted once per individual tool invocation as it
starts. Payload includes `tool_name`, `tool_args`, and `call_id`.
- `tool_success` — a tool finished successfully. Payload includes
`tool_name`, `summary`, `call_id`, and any `record_info`.
- `tool_error` — a tool invocation failed. Payload includes
`tool_name`, `error`, and `call_id`.
- `restreaming` — the LLM is being restarted with new context, for
example before a citation-verification pass.
Clients should ignore unknown event names rather than treating them
as errors.
properties:
event:
type: string
enum:
- connected
- status
- answer_chunk
- tool_calls
- tool_call
- tool_success
- tool_error
- restreaming
- complete
- error
data:
type: string
description: JSON-encoded event payload. Shape depends on `event`.
AgentStreamSSEEvent:
type: object
description: |
SSE event envelope for `POST /agents/{agentKey}/conversations/stream`.
Event names are listed in `event`; payload JSON is carried in `data`.
properties:
event:
type: string
description: |
SSE event name.
See the enum for possible values.
enum:
- connected
- status
- tool_calls
- tool_call
- tool_success
- tool_error
- tool_result
- tool_execution_complete
- answer_chunk
- restreaming
- metadata
- complete
- error
data:
type: string
description: |
JSON-encoded event payload.
Shape depends on `event`.
AgentMessageStreamSSEEvent:
type: object
description: |
Server-Sent Event envelope for `POST /agents/{agentKey}/conversations/{conversationId}/messages/stream`.
`data` is a JSON-encoded string whose shape depends on `event`.
Three events have stable API-defined payloads:
- `connected` — `{ "message": "SSE connection established" }`. Fired once
after the SSE stream opens. No `conversationId` is included because it is already
present in the request path.
- `complete` — `{ "conversation": AgentConversation, "recordsUsed": number,
"meta": { "requestId": string, "timestamp": string, "duration": number,
"recordsUsed": number } }`. Fired once after the upstream AI `complete` payload
is parsed, citations are saved, and the updated conversation is persisted.
- `error` — `{ "error": string, "details"?: string }`. Fired for runtime failures
after the stream has already started, including conversation lookup failures,
upstream AI startup failures, save failures, and stream transport errors.
All other events are forwarded from the upstream agent backend. Common event names:
- `status` — progress update for the current agent phase.
- `answer_chunk` — incremental token batch with running accumulated text.
- `tool_calls` / `tool_call` / `tool_success` / `tool_error` / `tool_result` /
`tool_execution_complete` — tool lifecycle events emitted by the upstream agent.
- `restreaming` — the upstream agent restarted generation with refreshed context.
- `metadata` — auxiliary metadata or keep-alive payload from the upstream agent.
Important wire behavior:
- The upstream agent's `complete` event is consumed server-side and replaced with the
API-defined `complete` event above.
- If the upstream `complete` payload cannot be parsed as JSON, the raw upstream
`complete` frame is forwarded unchanged instead.
- Unknown future event names may appear and should be ignored by clients.
properties:
event:
type: string
enum:
- connected
- status
- tool_calls
- tool_call
- tool_success
- tool_error
- tool_result
- tool_execution_complete
- answer_chunk
- restreaming
- metadata
- complete
- error
data:
type: string
description: JSON-encoded event payload. Shape depends on `event`.
ModelType:
type: string
enum:
- llm
- embedding
- ocr
- slm
- reasoning
- multiModal
- imageGeneration
- tts
- stt
description: Type of AI model
WebSearchProviderType:
type: string
enum:
- duckduckgo
- serper
- tavily
- exa
description: Supported web search provider
WebSearchProviderItem:
type: object
additionalProperties: false
description: Web search provider configuration item returned by getWebSearchProviders
required:
- provider
- providerKey
- configuration
- isDefault
properties:
provider:
$ref: '#/components/schemas/WebSearchProviderType'
providerKey:
type: string
description: Unique key for the provider configuration
configuration:
type: object
description: |
Provider-specific configuration as stored and returned by the gateway (open record).
Serper, Tavily, and Exa typically include `apiKey`; additional keys may be present.
additionalProperties: true
isDefault:
type: boolean
WebSearchSettings:
type: object
additionalProperties: false
description: Normalized web search global settings returned by getWebSearchProviders
required:
- includeImages
properties:
includeImages:
type: boolean
description: Whether to include images in search results
maxImages:
type: integer
minimum: 1
maximum: 500
description: Maximum number of images to return when includeImages is true
WebSearchProvidersResponse:
type: object
additionalProperties: false
description: Response for getWebSearchProviders
required:
- status
- providers
- settings
- message
properties:
status:
type: string
enum:
- success
providers:
type: array
items:
$ref: '#/components/schemas/WebSearchProviderItem'
settings:
$ref: '#/components/schemas/WebSearchSettings'
message:
type: string
description: Human-readable status (empty list vs populated providers)
security:
- bearerAuth: []
- oauth2: []
paths:
/oauth2/token:
post:
tags:
- OAuth Provider
summary: Exchange authorization code for tokens
description: |
OAuth 2.0 Token Endpoint (RFC 6749 Section 4.1.3).
Exchanges an authorization code, client credentials, or refresh token for access tokens.
**Grant Types:**
- `authorization_code`: Exchange auth code for tokens (user-based)
- `client_credentials`: Get tokens for machine-to-machine auth
- `refresh_token`: Get new access token using refresh token
For **`client_credentials`**, access tokens represent the **OAuth app creator** (the user who registered the client). The JWT may encode **`userId === client_id`**; the **Node API gateway** resolves the creator (**`createdBy`** claim or OAuth app lookup) — see **OAuth Provider** tag.
**Client Authentication:**
Can be provided via:
- HTTP Basic auth: `Authorization: Basic base64(client_id:client_secret)`
- Request body: `client_id` and `client_secret` parameters
**PKCE Verification:**
If authorization used PKCE, the `code_verifier` must be provided and will be
verified against the stored code challenge.
operationId: oauthToken
security: []
requestBody:
description: Request payload
content:
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/OAuthTokenRequest'
application/json:
schema:
$ref: '#/components/schemas/OAuthTokenRequest'
required: true
responses:
'200':
description: Tokens issued successfully
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthTokenResponse'
example:
access_token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
token_type: Bearer
expires_in: 3600
refresh_token: dGhpcyBpcyBhIHJlZnJlc2ggdG9rZW4...
scope: openid profile email
id_token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
'400':
description: Invalid request (missing parameters, invalid code, etc.)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Client authentication failed
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthErrorResponse'
'429':
description: Rate limit exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthClientManagementRateLimitError'
/oauth2/revoke:
post:
tags:
- OAuth Provider
summary: Revoke an access or refresh token
description: |
OAuth 2.0 Token Revocation Endpoint (RFC 7009).
Revokes an access token or refresh token, preventing further use.
Revoking a refresh token also invalidates associated access tokens.
**Use Cases:**
- User logs out of third-party app
- User revokes app access from account settings
- Security incident response
**Note:** Returns 200 OK even if token was already revoked or invalid
(per RFC 7009, to prevent token enumeration).
operationId: oauthRevoke
security: []
requestBody:
description: Request payload
content:
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/OAuthRevokeRequest'
application/json:
schema:
$ref: '#/components/schemas/OAuthRevokeRequest'
required: true
responses:
'200':
description: Token revoked (or was already invalid)
'401':
description: Client authentication failed
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthErrorResponse'
'429':
description: Rate limit exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthClientManagementRateLimitError'
/oauth2/introspect:
post:
tags:
- OAuth Provider
summary: Introspect a token
description: |
OAuth 2.0 Token Introspection Endpoint (RFC 7662).
Check if a token is active and retrieve its metadata.
**Use Cases:**
- Resource servers validating tokens
- Debugging token issues
- Checking token scopes before processing requests
**Response:**
- Active token: Returns `active: true` with token metadata
- Invalid/expired/revoked token: Returns only `active: false`
operationId: oauthIntrospect
security: []
requestBody:
description: Request payload
content:
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/OAuthIntrospectRequest'
application/json:
schema:
$ref: '#/components/schemas/OAuthIntrospectRequest'
required: true
responses:
'200':
description: Token introspection result
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthIntrospectResponse'
examples:
active:
summary: Active token
value:
active: true
scope: openid profile email
client_id: abc123
username: user@example.com
token_type: Bearer
exp: 1735686000
iat: 1735682400
user_id: user-id-123
iss: https://api.pipeshub.com
inactive:
summary: Inactive/invalid token
value:
active: false
'401':
description: Client authentication failed
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthErrorResponse'
'429':
description: Rate limit exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthClientManagementRateLimitError'
/oauth2/userinfo:
get:
tags:
- OpenID Connect
summary: Get authenticated user information
description: |
OpenID Connect UserInfo Endpoint.
Returns claims about the authenticated user. Requires a valid access token
with the `openid` scope.
**Available Claims:**
- `user_id` - User identifier
- `name`, `given_name`, `family_name` - Name claims (with `profile` scope)
- `email`, `email_verified` - Email claims (with `email` scope)
**Authentication:**
Pass the access token as a Bearer token: `Authorization: Bearer {access_token}`
operationId: oauthUserInfo
security:
- bearerAuth: []
responses:
'200':
description: User information
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthUserInfoResponse'
example:
user_id: user-id-123
name: John Doe
given_name: John
family_name: Doe
email: john.doe@example.com
email_verified: true
'401':
description: Invalid or missing access token
'403':
description: Token does not have openid scope
/oauth-clients:
get:
tags:
- OAuth Apps
summary: List OAuth apps
description: |
Returns a paginated list of OAuth apps registered by the signed-in user. Access is creator-scoped — even org admins only see apps they created themselves, so this endpoint is safe to use for per-user developer dashboards without leaking org-wide app metadata.
Each entry carries the full app configuration except the client secret, which is only ever returned at creation time and immediately after a regeneration.
Use the `status` query parameter to filter by lifecycle state (`active`, `suspended`, `revoked`) and `search` for a case-insensitive substring match against `name` or `description`.
operationId: listOAuthApps
security:
- bearerAuth: []
parameters:
- name: page
in: query
schema:
type: integer
minimum: 1
default: 1
description: |
Page number (matches `listAppsQuerySchema`: defaults to `1` when omitted or empty).
- name: limit
in: query
schema:
type: integer
minimum: 1
maximum: 100
default: 20
description: |
Items per page (defaults to `20` when omitted or empty; max 100).
- name: status
in: query
schema:
type: string
enum:
- active
- suspended
- revoked
description: Filter by status
- name: search
in: query
schema:
type: string
description: Search by app name or description (case-insensitive)
responses:
'200':
description: List of OAuth apps
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthAppListResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ApplicationJsonErrorResponse'
'403':
description: Forbidden — insufficient workspace permission to list OAuth apps
content:
application/json:
schema:
$ref: '#/components/schemas/ApplicationJsonErrorResponse'
'429':
description: Rate limit exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthClientManagementRateLimitError'
post:
tags:
- OAuth Apps
summary: Create OAuth app
description: |
Register a new OAuth app for the organization. Any authenticated org member may create apps; the creator is recorded as the app's owner and is the only user who can subsequently read, update, suspend, activate, regenerate the secret of, or delete it.
The `clientSecret` is returned in this response **only** — it is stored hashed server-side and cannot be retrieved later. Persist it before exiting the create flow; if it is ever lost, rotate via `POST /oauth-clients/{appId}/regenerate-secret`.
`allowedScopes` is validated against the caller's role-aware scope set (see `GET /oauth-clients/scopes`). Org admins may include admin-only scopes; non-admins requesting a restricted scope receive `400`.
All `/oauth-clients/*` routes share a per-user rate limiter (default 1000 req/min, configurable via the `MAX_OAUTH_CLIENT_REQUESTS_PER_MINUTE` env var).
operationId: createOAuthApp
security:
- bearerAuth: []
requestBody:
description: Request body for Create OAuth app
content:
application/json:
schema:
$ref: '#/components/schemas/CreateOAuthAppRequest'
required: true
responses:
'201':
description: OAuth app created successfully
content:
application/json:
schema:
$ref: '#/components/schemas/CreateOAuthAppResponse'
'400':
description: Invalid request (validation error)
content:
application/json:
schema:
$ref: '#/components/schemas/ApplicationJsonErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ApplicationJsonErrorResponse'
'403':
description: Forbidden — insufficient workspace permission to create OAuth apps
content:
application/json:
schema:
$ref: '#/components/schemas/ApplicationJsonErrorResponse'
'429':
description: Rate limit exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthClientManagementRateLimitError'
/oauth-clients/scopes:
get:
tags:
- OAuth Apps
summary: List available scopes
description: |
Returns the OAuth scopes the signed-in user is permitted to register on new or updated apps, grouped by category. Use this to populate scope-picker UIs and to validate `allowedScopes` client-side before submitting to `createOAuthApp` / `updateOAuthApp`.
The result is role-aware. Org admins (members of an admin user group) receive every registered scope; everyone else is filtered to exclude admin-only scopes: `org:write`, `org:admin`, `user:invite`, `user:delete`, `usergroup:write`, `team:write`, `config:write`, `crawl:write`, `crawl:delete`.
Each key in the `scopes` map matches the `category` field on the `OAuthScopeInfo` entries it contains. A category may appear with an empty array when every scope it contains is restricted for the caller — treat empty buckets as "no permitted scopes in this group", not as a missing category.
Shares the per-user rate limiter applied to every `/oauth-clients/*` route (default 1000 req/min, `MAX_OAUTH_CLIENT_REQUESTS_PER_MINUTE`).
operationId: listOAuthScopes
security:
- bearerAuth: []
responses:
'200':
description: List of available scopes
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthScopesGroupedResponse'
example:
scopes:
Identity:
- name: openid
description: OpenID Connect authentication
category: Identity
requiresUserConsent: false
- name: profile
description: User profile information (name, picture)
category: Identity
requiresUserConsent: true
Knowledge Base:
- name: kb:read
description: Read knowledge bases and records
category: Knowledge Base
requiresUserConsent: true
'401':
description: Unauthorized — missing/invalid token, or session invalidated (e.g. password change after token issuance)
content:
application/json:
schema:
$ref: '#/components/schemas/ApplicationJsonErrorResponse'
'429':
description: Rate limit exceeded for OAuth client management routes
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthClientManagementRateLimitError'
example:
error:
code: TOO_MANY_REQUESTS
message: Too many OAuth client requests. Please try again later.
retryAfter: 45
/oauth-clients/{appId}:
get:
tags:
- OAuth Apps
summary: Get OAuth app details
description: |
Returns the full configuration of an OAuth app you registered. The `clientSecret` is never echoed back here; if you need a new one, call `POST /oauth-clients/{appId}/regenerate-secret`.
Access is creator-scoped: even org admins receive `404` for apps owned by other users. This avoids leaking app metadata across org members and keeps the read surface symmetric with `listOAuthApps`.
operationId: getOAuthApp
security:
- bearerAuth: []
parameters:
- name: appId
in: path
required: true
schema:
type: string
pattern: ^[a-fA-F0-9]{24}$
description: OAuth app ID (MongoDB ObjectId)
responses:
'200':
description: OAuth app details
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthAppResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ApplicationJsonErrorResponse'
'403':
description: Forbidden — caller cannot access this OAuth app (creator-only; see OAuth Apps tag).
content:
application/json:
schema:
$ref: '#/components/schemas/ApplicationJsonErrorResponse'
'404':
description: OAuth app not found or not visible to this caller (each user only sees apps they created)
content:
application/json:
schema:
$ref: '#/components/schemas/ApplicationJsonErrorResponse'
'429':
description: Rate limit exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthClientManagementRateLimitError'
put:
tags:
- OAuth Apps
summary: Update OAuth app
description: |
Update an OAuth app's configuration. All body fields are optional — supply only what should change. URL fields (`homepageUrl`, `privacyPolicyUrl`, `termsOfServiceUrl`) accept `null` to clear them.
Creator-only: even org admins cannot edit apps owned by other users.
When modifying `allowedScopes`, the new set must remain a subset of the caller's role-aware scope list (same rule as `GET /oauth-clients/scopes`). When adding `authorization_code` to `allowedGrantTypes`, `redirectUris` becomes required and must contain at least one URI; otherwise the request is rejected with `400` by the Zod refine on `updateAppSchema`.
This endpoint never rotates the client secret — use `POST /oauth-clients/{appId}/regenerate-secret` for that.
operationId: updateOAuthApp
security:
- bearerAuth: []
parameters:
- name: appId
in: path
required: true
schema:
type: string
pattern: ^[a-fA-F0-9]{24}$
description: OAuth app ID
requestBody:
description: Request payload
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateOAuthAppRequest'
required: true
responses:
'200':
description: OAuth app updated
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateOAuthAppResponse'
'400':
description: Validation error
content:
application/json:
schema:
$ref: '#/components/schemas/ApplicationJsonErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ApplicationJsonErrorResponse'
'403':
description: Forbidden — caller cannot access this OAuth app (creator-only; see OAuth Apps tag).
content:
application/json:
schema:
$ref: '#/components/schemas/ApplicationJsonErrorResponse'
'404':
description: OAuth app not found or not visible to this caller (each user only sees apps they created)
content:
application/json:
schema:
$ref: '#/components/schemas/ApplicationJsonErrorResponse'
'429':
description: Rate limit exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthClientManagementRateLimitError'
delete:
tags:
- OAuth Apps
summary: Delete OAuth app
description: |
Soft-deletes an OAuth app. The app is flagged `isDeleted=true` on the `OAuthApp` document, removed from list/get responses for every caller, and all of its access and refresh tokens are revoked in the same operation. There is no restore endpoint — deletion is final.
Creator-only: even org admins cannot delete apps owned by other users.
operationId: deleteOAuthApp
security:
- bearerAuth: []
parameters:
- name: appId
in: path
required: true
schema:
type: string
pattern: ^[a-fA-F0-9]{24}$
description: OAuth app ID
responses:
'200':
description: OAuth app deleted
content:
application/json:
schema:
type: object
properties:
message:
type: string
example: OAuth app deleted successfully
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ApplicationJsonErrorResponse'
'403':
description: Forbidden — caller cannot access this OAuth app (creator-only; see OAuth Apps tag).
content:
application/json:
schema:
$ref: '#/components/schemas/ApplicationJsonErrorResponse'
'404':
description: OAuth app not found or not visible to this caller (each user only sees apps they created)
content:
application/json:
schema:
$ref: '#/components/schemas/ApplicationJsonErrorResponse'
'429':
description: Rate limit exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthClientManagementRateLimitError'
/oauth-clients/{appId}/regenerate-secret:
post:
tags:
- OAuth Apps
summary: Regenerate client secret
description: |
Generates a fresh client secret for an OAuth app. The previous secret is invalidated immediately — any client still presenting it will fail token exchange at `POST /oauth2/token` until updated.
The new secret is returned in this response **only** and cannot be retrieved later. Pair this call with credential propagation to every integration that uses the app. If the rotation was triggered by a suspected leak, also call `POST /oauth-clients/{appId}/revoke-all-tokens` to invalidate already-issued access and refresh tokens instead of waiting for their natural expiry.
Creator-only: even org admins cannot rotate secrets for other users' apps.
operationId: regenerateOAuthAppSecret
security:
- bearerAuth: []
parameters:
- name: appId
in: path
required: true
schema:
type: string
pattern: ^[a-fA-F0-9]{24}$
description: OAuth app ID
responses:
'200':
description: New client secret generated
content:
application/json:
schema:
$ref: '#/components/schemas/RegenerateOAuthAppSecretResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ApplicationJsonErrorResponse'
'403':
description: Forbidden — caller cannot access this OAuth app (creator-only; see OAuth Apps tag).
content:
application/json:
schema:
$ref: '#/components/schemas/ApplicationJsonErrorResponse'
'404':
description: OAuth app not found or not visible to this caller (each user only sees apps they created)
content:
application/json:
schema:
$ref: '#/components/schemas/ApplicationJsonErrorResponse'
'429':
description: Rate limit exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthClientManagementRateLimitError'
/oauth-clients/{appId}/suspend:
post:
tags:
- OAuth Apps
summary: Suspend OAuth app
description: |
Moves an OAuth app to `status: "suspended"`, blocking new token issuance at `POST /oauth2/token` and the authorization-code consent flow. Tokens that have already been issued remain valid until their natural expiry — call `POST /oauth-clients/{appId}/revoke-all-tokens` immediately afterwards if you need an immediate lockout.
Use this for temporary suspensions where you intend to reactivate later. For permanent removal, use `DELETE /oauth-clients/{appId}`. Suspending an app that is already suspended returns `400`.
Creator-only.
operationId: suspendOAuthApp
security:
- bearerAuth: []
parameters:
- name: appId
in: path
required: true
schema:
type: string
pattern: ^[a-fA-F0-9]{24}$
description: OAuth app ID
responses:
'200':
description: OAuth app suspended
content:
application/json:
schema:
$ref: '#/components/schemas/SuspendOAuthAppResponse'
'400':
description: Bad request — e.g. OAuth app is already suspended
content:
application/json:
schema:
$ref: '#/components/schemas/ApplicationJsonErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ApplicationJsonErrorResponse'
'403':
description: Forbidden — caller cannot access this OAuth app (creator-only; see OAuth Apps tag).
content:
application/json:
schema:
$ref: '#/components/schemas/ApplicationJsonErrorResponse'
'404':
description: OAuth app not found or not visible to this caller (each user only sees apps they created)
content:
application/json:
schema:
$ref: '#/components/schemas/ApplicationJsonErrorResponse'
'429':
description: Rate limit exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthClientManagementRateLimitError'
/oauth-clients/{appId}/activate:
post:
tags:
- OAuth Apps
summary: Activate suspended OAuth app
description: |
Moves a suspended OAuth app back to `status: "active"`, restoring its ability to authenticate and obtain new tokens via `POST /oauth2/token`.
A revoked app cannot be reactivated (returns `400`); the only path back is to register a new app. Activating an app that is already active also returns `400`.
Creator-only.
operationId: activateOAuthApp
security:
- bearerAuth: []
parameters:
- name: appId
in: path
required: true
schema:
type: string
pattern: ^[a-fA-F0-9]{24}$
description: OAuth app ID
responses:
'200':
description: OAuth app activated
content:
application/json:
schema:
$ref: '#/components/schemas/ActivateOAuthAppResponse'
'400':
description: Bad request — e.g. app is already active, or cannot activate a revoked app
content:
application/json:
schema:
$ref: '#/components/schemas/ApplicationJsonErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ApplicationJsonErrorResponse'
'403':
description: Forbidden — caller cannot access this OAuth app (creator-only; see OAuth Apps tag).
content:
application/json:
schema:
$ref: '#/components/schemas/ApplicationJsonErrorResponse'
'404':
description: OAuth app not found or not visible to this caller (each user only sees apps they created)
content:
application/json:
schema:
$ref: '#/components/schemas/ApplicationJsonErrorResponse'
'429':
description: Rate limit exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthClientManagementRateLimitError'
/oauth-clients/{appId}/tokens:
get:
tags:
- OAuth Apps
summary: List app tokens
description: |
Lists active access and refresh tokens currently issued to an OAuth app, sorted newest first. Useful for auditing app usage and picking specific tokens to investigate before a targeted revocation.
Each entry includes the token type (`access` or `refresh`), the user the token was issued for (omitted for client-credentials access tokens), the granted scopes, the issuance and expiry timestamps, and the revocation flag. Each type is capped at 100 most-recent rows server-side (`listTokensForApp` in `oauth_token.service.ts`); revoked and expired tokens are excluded.
Creator-only.
operationId: listOAuthAppTokens
security:
- bearerAuth: []
parameters:
- name: appId
in: path
required: true
schema:
type: string
pattern: ^[a-fA-F0-9]{24}$
description: OAuth app ID
responses:
'200':
description: List of tokens
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthAppTokensListResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ApplicationJsonErrorResponse'
'403':
description: Forbidden — caller cannot access this OAuth app (creator-only; see OAuth Apps tag).
content:
application/json:
schema:
$ref: '#/components/schemas/ApplicationJsonErrorResponse'
'404':
description: OAuth app not found or not visible to this caller (each user only sees apps they created)
content:
application/json:
schema:
$ref: '#/components/schemas/ApplicationJsonErrorResponse'
'429':
description: Rate limit exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthClientManagementRateLimitError'
/oauth-clients/{appId}/revoke-all-tokens:
post:
tags:
- OAuth Apps
summary: Revoke all app tokens
description: |
Revokes every access and refresh token currently issued to an OAuth app, in a single operation. Use this for emergency credential rotation, suspected secret leaks, or as a follow-up to `POST /oauth-clients/{appId}/regenerate-secret` when you want existing sessions invalidated immediately rather than letting them expire naturally.
The response `count` is the total number of tokens revoked across both types. Clients of this app must then obtain new tokens via the standard OAuth flow.
Creator-only.
operationId: revokeAllOAuthAppTokens
security:
- bearerAuth: []
parameters:
- name: appId
in: path
required: true
schema:
type: string
pattern: ^[a-fA-F0-9]{24}$
description: OAuth app ID
responses:
'200':
description: All tokens revoked
content:
application/json:
schema:
type: object
properties:
message:
type: string
example: All tokens revoked successfully
count:
type: integer
description: Number of tokens revoked
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ApplicationJsonErrorResponse'
'403':
description: Forbidden — caller cannot access this OAuth app (creator-only; see OAuth Apps tag).
content:
application/json:
schema:
$ref: '#/components/schemas/ApplicationJsonErrorResponse'
'404':
description: OAuth app not found or not visible to this caller (each user only sees apps they created)
content:
application/json:
schema:
$ref: '#/components/schemas/ApplicationJsonErrorResponse'
'429':
description: Rate limit exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthClientManagementRateLimitError'
/userAccount/initAuth:
post:
tags:
- User Account
summary: Initialize authentication session
description: |
Start a server-side authentication session and discover which sign-in methods are
configured for the organization. This is the first step in the multi-step login flow.
**Request body (optional)**
- You may omit the body, send an empty JSON object `{}`, or send `{ "email": "..." }`.
- `email` in the body is optional and kept for legacy reasons; omitting it does not prevent
initialization. The web client typically calls this endpoint without a body and sends
`email` on `/authenticate` instead.
- When provided, `email` is stored on the session for correlation with subsequent steps.
**Flow:**
1. Call this endpoint (optional JSON body as above).
2. Receive a session token in the `x-session-token` response header.
3. Send that token on subsequent `/authenticate` requests (`x-session-token` header).
4. Use `allowedMethods` and `authProviders` from the response to render the login UI.
**Session token**
- Returned as header `x-session-token`.
- Required for `/authenticate` (and related steps) until it expires.
**Multi-factor authentication**
If the organization has MFA, complete multiple authentication steps; each step may
return the next step's allowed methods.
operationId: initAuth
security: []
requestBody:
description: |
Optional. Omit entirely or send `{}`. You may include `email` for legacy compatibility (pre-fills the session); invalid `email` format is rejected when the field is present.
content:
application/json:
schema:
$ref: '#/components/schemas/InitAuthRequest'
required: false
responses:
'200':
description: Authentication session initialized successfully
headers:
x-session-token:
schema:
type: string
description: Session token for subsequent authentication requests. Store this securely.
content:
application/json:
schema:
$ref: '#/components/schemas/InitAuthResponse'
'400':
description: Invalid request (e.g. malformed `email` when that property is sent)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/userAccount/authenticate:
post:
tags:
- User Account
summary: Authenticate user with credentials
description: |
Authenticate a user using the specified method and credentials.
Requires a valid session token from `/initAuth`.
**Credential Formats by Method:**
- `password`: `{ "credentials": { "password": "your-password" } }`
- `otp`: `{ "credentials": { "otp": "123456" } }` (6-digit code, valid for 10 minutes)
- `google`: `{ "credentials": "google-id-token-string" }`
- `microsoft`: `{ "credentials": { "accessToken": "...", "idToken": "..." } }`
- `azureAd`: `{ "credentials": { "accessToken": "...", "idToken": "..." } }`
- `oauth`: `{ "credentials": { "accessToken": "...", "idToken": "..." } }`
- `samlSso`: Handled via redirect flow (use `/saml/signIn` instead)
**Multi-Step Response:**
If organization uses MFA, successful authentication returns:
- `status: "success"` with `nextStep` and `allowedMethods` for next step
**Fully Authenticated Response:**
After completing all steps:
- `message: "Fully authenticated"` with `accessToken` (1hr) and `refreshToken` (7d)
**Security:**
- Account locks after 5 consecutive failed attempts
- CAPTCHA may be required if enabled (pass `cf-turnstile-response`)
operationId: authenticate
security: []
parameters:
- name: x-session-token
in: header
required: true
description: Session token received from `/initAuth` endpoint
schema:
type: string
requestBody:
description: Request payload
content:
application/json:
schema:
$ref: '#/components/schemas/AuthenticateRequest'
required: true
responses:
'200':
description: Authentication step successful or fully authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/AuthenticateResponse'
'400':
description: Invalid request, method not allowed, invalid credential format or Account blocked due to too many failed attempts (5 attempts max)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Invalid credentials (wrong password, expired OTP, etc.)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Session expired or user not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'410':
description: OTP has expired (valid for 10 minutes)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/userAccount/refresh/token:
post:
tags:
- User Account
summary: Refresh access token
description: |
Get a new access token using a valid refresh token.
**Usage:**
- Pass the refresh token as a Bearer token in the Authorization header
- Returns a new access token and basic user information
**Token Lifetimes:**
- Access token: 24 hours (configurable via `ACCESS_TOKEN_EXPIRY` environment variable)
- Refresh token: 30 days (configurable via `REFRESH_TOKEN_EXPIRY` environment variable)
**Best Practices:**
- Call this endpoint before the access token expires
- Store the new access token and continue using it for authenticated requests
- If refresh fails with 401, redirect user to login flow
operationId: refreshToken
security:
- scopedToken: []
responses:
'200':
description: Token refreshed successfully
content:
application/json:
schema:
$ref: '#/components/schemas/RefreshTokenResponse'
'400':
description: Disabled user account
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Invalid or expired refresh token - user must re-authenticate
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: User not found (account may have been deleted), User credentials not found, or Organization not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/userAccount/password/reset:
post:
tags:
- User Account
summary: Reset password
description: |
Reset the password for the currently authenticated user.
**Overview:**
Allows a logged-in user to change their password by providing the current password and a new password.
operationId: resetPassword
security:
- bearerAuth: []
requestBody:
required: true
description: Request payload
content:
application/json:
schema:
type: object
additionalProperties: false
required:
- currentPassword
- newPassword
properties:
currentPassword:
type: string
format: password
newPassword:
type: string
format: password
cf-turnstile-response:
type: string
description: Cloudflare Turnstile CAPTCHA token (required when Turnstile is configured server-side)
responses:
'200':
description: Password reset successfully - returns new access token
content:
application/json:
schema:
$ref: '#/components/schemas/AuthenticatedPasswordResetResponse'
'400':
description: |
Bad request. Possible causes:
- `currentPassword` or `newPassword` missing from request body
- Current and new password are the same (plain-text comparison)
- New password does not meet strength requirements (min 8 chars, uppercase, lowercase, number, special character)
- Old and new password are the same (hash comparison against stored password)
- Account is blocked due to too many incorrect login attempts
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: |
Unauthorized. Possible causes:
- Invalid or expired access token
- Current password is incorrect
- Invalid CAPTCHA verification (when Turnstile is configured)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: |
Not found. Possible causes:
- Auth container not found
- User credentials not found (no password set for account)
- User not found in IAM service
- Organization not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/orgAuthConfig/authMethods:
get:
tags:
- Organization Auth Config
summary: Get organization authentication methods
description: |
Retrieve the configured authentication methods for the organization.
**Response Structure:**
Returns an array of authentication steps, each containing:
- `order`: Step number (1-3)
- `allowedMethods`: Array of methods allowed for that step
**Example Response:**
```json
{
"authMethods": [
{ "order": 1, "allowedMethods": [{ "type": "password" }, { "type": "google" }] },
{ "order": 2, "allowedMethods": [{ "type": "otp" }] }
]
}
```
**Admin Access Required:** Only organization admins can view auth configuration.
operationId: getAuthMethods
security:
- bearerAuth: []
responses:
'200':
description: Authentication methods retrieved successfully
content:
application/json:
schema:
$ref: '#/components/schemas/AuthConfig'
'400':
description: |
Bad request. Possible causes:
- User is not an organization admin
- User not authenticated (token decoded but `req.user` is null)
- Organization ID missing from token payload
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Unauthorized - invalid or expired access token
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: |
Not found. Possible causes:
- Auth container not found
- Account not found (userId or orgId missing)
- Admin check failed in IAM service
- Organization auth configuration not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/orgAuthConfig/updateAuthMethod:
post:
tags:
- Organization Auth Config
summary: Update organization authentication methods
description: |
Update the authentication methods configuration for an organization.
This allows admins to configure single or multi-factor authentication.
**Validation Rules:**
- Minimum 1 step, maximum 3 steps
- Each step must have a unique order (1, 2, or 3)
- No duplicate methods within the same step
- No method can appear in multiple steps
- Each step must have at least one allowed method
**Available Methods:**
- `password`: Email/password authentication
- `otp`: One-time password via email
- `google`: Google OAuth 2.0
- `microsoft`: Microsoft OAuth 2.0
- `azureAd`: Azure Active Directory
- `samlSso`: SAML 2.0 Single Sign-On
- `oauth`: Generic OAuth 2.0 provider
**Example - Single Factor (Password or Google):**
```json
{
"authMethod": [
{ "order": 1, "allowedMethods": [{ "type": "password" }, { "type": "google" }] }
]
}
```
**Example - Two Factor (Password + OTP):**
```json
{
"authMethod": [
{ "order": 1, "allowedMethods": [{ "type": "password" }] },
{ "order": 2, "allowedMethods": [{ "type": "otp" }] }
]
}
```
**Admin Access Required:** Only organization admins can update auth configuration.
operationId: updateAuthMethod
security:
- bearerAuth: []
requestBody:
description: Request payload
required: true
content:
application/json:
schema:
type: object
additionalProperties: false
required:
- authMethod
properties:
authMethod:
type: array
description: Authentication steps to set for the organization (1-3 steps)
minItems: 1
maxItems: 3
items:
$ref: '#/components/schemas/AuthStep'
responses:
'200':
description: Authentication methods updated successfully
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateAuthMethodResponse'
'400':
description: |
Bad request. Possible causes:
- User is not an organization admin
- `authMethod` field missing from request body
- Validation failure (duplicate steps, duplicate methods, out-of-range order, empty methods array)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: |
Unauthorized. Possible causes:
- Invalid or expired access token
- User not authenticated (token decoded but `req.user` is null)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: |
Not found. Possible causes:
- Auth container not found
- Account not found (userId or orgId missing)
- Admin check failed in IAM service
- Organization auth configuration not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/orgAuthConfig:
post:
tags:
- Organization Auth Config
summary: Set up auth configuration
description: |
Set up or initialize the organization's authentication configuration.
operationId: setUpAuthConfig
security:
- bearerAuth: []
requestBody:
required: true
description: Organization setup details
content:
application/json:
schema:
$ref: '#/components/schemas/OrgAuthConfigCreateRequest'
responses:
'200':
description: Auth configuration already exists for this deployment
content:
application/json:
schema:
$ref: '#/components/schemas/OrgAuthConfigSetupResponse'
'201':
description: Auth configuration created successfully
content:
application/json:
schema:
$ref: '#/components/schemas/OrgAuthConfigSetupResponse'
'400':
description: |
Bad request. Possible causes:
- User is not an organization admin
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Unauthorized - invalid or expired access token
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: |
Not found. Possible causes:
- Auth container not found
- Account not found (userId or orgId missing)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/org:
get:
tags:
- Organizations
summary: Get current organization
description: |
Retrieve details about the authenticated user's organization.
**Overview:**
This endpoint returns the organization document for the current user's org, including profile data and configuration.
**Response Includes:**
- Organization profile (registeredName, shortName, contactEmail, domain)
- Account type
- Onboarding status
- Permanent address
- Creation and modification timestamps
**Use Cases:**
- Organization profile pages
- Settings and configuration screens
operationId: getCurrentOrganization
security:
- bearerAuth: []
- oauth2:
- org:read
responses:
'200':
description: Organization details retrieved successfully
content:
application/json:
schema:
$ref: '#/components/schemas/Organization'
'401':
description: Unauthorized - Valid bearer token required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Organization not found - User's organization does not exist
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal server error - Database query failure
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/knowledgeBase:
post:
tags:
- Knowledge Base
summary: Create a new knowledge base
description: |
Create a new knowledge base for organizing and managing documents within your organization.
**Overview:**
A knowledge base is a container for organizing related documents, files, and content. It provides a central location for teams to collaborate on shared information.
**Features:**
- Hierarchical folder structure support
- Role-based access control (OWNER, WRITER, READER)
- Full-text search across all records
- Integration with external connectors (Google Drive, OneDrive, etc.)
- Automatic content indexing for AI-powered search
**Naming Rules:**
- Name must be 1-255 characters
- Special characters and HTML tags are sanitized
- Names don't need to be unique within organization
**Creator Permissions:**
The user creating the KB automatically becomes the OWNER with full administrative rights.
operationId: createKnowledgeBase
security:
- bearerAuth: []
- oauth2:
- kb:write
requestBody:
required: true
description: Request payload
content:
application/json:
schema:
type: object
properties:
kbName:
type: string
minLength: 1
maxLength: 255
description: Name of the knowledge base
example: Product Documentation
required:
- kbName
responses:
'200':
description: Knowledge base created successfully
content:
application/json:
schema:
$ref: '#/components/schemas/KnowledgeBaseCreateResponse'
'400':
description: |
**Invalid request:**
- Name too short or too long
- Invalid characters in name
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Unauthorized - Valid bearer token required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: |
Forbidden. Possible reasons:
- OAuth token lacks the `kb:write` scope
- Connector service denied the request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: User not found - Authenticated user does not exist in the graph database
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal server error - Knowledge base creation failed in connector or database
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'503':
description: Service unavailable - Connector service is unreachable
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
get:
tags:
- Knowledge Base
summary: List all knowledge bases
description: |
Retrieve a paginated list of all knowledge bases accessible to the authenticated user.
**Overview:**
Returns knowledge bases where the user has at least READER permission. Results include the user's role for each KB.
**Filtering:**
- **search:** Full-text search on KB names (max 1000 chars)
- **permissions:** Filter by user's role (comma-separated: OWNER, WRITER, READER)
**Sorting Options:**
- `name` — Alphabetical by KB name
- `createdAtTimestamp` — By creation date
- `updatedAtTimestamp` — By last modification
- `userRole` — By permission level
**Performance:**
Uses efficient pagination with limit/offset. For large result sets, use smaller page sizes.
**Query parameters:**
Only `page`, `limit`, `search`, `permissions`, `sortBy`, and `sortOrder` are allowed; unknown query keys are rejected.
operationId: listKnowledgeBases
security:
- bearerAuth: []
- oauth2:
- kb:read
parameters:
- name: page
in: query
required: false
description: Page number (1-indexed). Omitted values default to 1.
schema:
type: integer
minimum: 1
default: 1
- name: limit
in: query
required: false
description: Results per page (max 100). Omitted values default to 20.
schema:
type: integer
minimum: 1
maximum: 100
default: 20
- name: search
in: query
required: false
description: |
Search KB names (max 1000 chars). Rejected if it contains HTML/script tags,
event handlers, `javascript:`, or format specifiers (validated in Zod + controller).
schema:
type: string
maxLength: 1000
- name: permissions
in: query
required: false
description: |
Comma-separated permission roles to filter by. Each token must be one of:
OWNER, WRITER, READER.
schema:
type: string
example: OWNER,WRITER
- name: sortBy
in: query
required: false
description: Field to sort by.
schema:
type: string
enum:
- name
- createdAtTimestamp
- updatedAtTimestamp
- userRole
default: name
- name: sortOrder
in: query
required: false
description: Sort direction.
schema:
type: string
enum:
- asc
- desc
default: asc
responses:
'200':
description: Successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/GetAllKnowledgeBaseResponseSchema'
'400':
description: |
**Invalid query parameters:**
- `page` not a positive integer
- `limit` not between 1 and 100
- Unknown query parameter (only `page`, `limit`, `search`, `permissions`, `sortBy`, `sortOrder` allowed)
- Invalid `sortBy` or `sortOrder`
- Invalid `permissions` role token
- `search` too long, or contains HTML/scripts/format specifiers
- Connector returned a 400 error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Unauthorized — valid bearer token required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: |
Forbidden. Possible reasons:
- OAuth token lacks the `kb:read` scope
- Connector service denied the request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: User not found — authenticated user does not exist in the graph database
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal server error — listing knowledge bases failed in connector or database
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'503':
description: Service unavailable — connector service is unreachable
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/knowledgeBase/{kbId}:
get:
tags:
- Knowledge Base
summary: Get knowledge base by ID
description: |
Retrieve detailed information about a specific knowledge base.
**Overview:**
Returns complete KB metadata including name, timestamps, root-level folders, and the requesting user's role.
**Access Control:**
User must have at least READER permission to view KB details.
operationId: getKnowledgeBase
security:
- bearerAuth: []
- oauth2:
- kb:read
parameters:
- name: kbId
in: path
required: true
description: Knowledge base ID (non-empty string)
schema:
type: string
minLength: 1
example: 8a095180-2989-4018-b448-70eb75fba1c7
responses:
'200':
description: Knowledge base retrieved successfully
content:
application/json:
schema:
$ref: '#/components/schemas/GetKnowledgeBaseById'
'401':
description: Unauthorized — valid bearer token required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: |
Forbidden. Possible reasons:
- OAuth token lacks the `kb:read` scope
- User does not have permission to access this knowledge base
- Connector service denied the request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: |
Not found. Possible reasons:
- Knowledge base does not exist
- Authenticated user does not exist in the graph database
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal server error — retrieving knowledge base failed in connector or database
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'503':
description: Service unavailable — connector service is unreachable
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
put:
tags:
- Knowledge Base
summary: Update knowledge base
description: |
Update a knowledge base's name.
**Required permission:**
User must have one of `OWNER` or `WRITER` on the knowledge base.
**Validation:**
- `kbId` path parameter must be a valid UUID (`updateKBSchema`)
- When provided, `kbName` must be 1–255 characters
- XSS and format-specifier checks are applied to `kbName` in the gateway controller
operationId: updateKnowledgeBase
security:
- bearerAuth: []
- oauth2:
- kb:write
parameters:
- name: kbId
in: path
required: true
description: Knowledge base ID (UUID)
schema:
type: string
format: uuid
example: 8a095180-2989-4018-b448-70eb75fba1c7
requestBody:
required: true
description: Fields to update. `kbName` is optional; an empty object is valid.
content:
application/json:
schema:
type: object
additionalProperties: false
properties:
kbName:
type: string
minLength: 1
maxLength: 255
description: New name for the knowledge base
example: Updated Documentation Hub
responses:
'200':
description: Knowledge base updated successfully
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateKnowledgeBaseById'
'400':
description: |
Invalid request. Possible reasons:
- `kbId` is not a valid UUID (gateway `updateKBSchema`)
- `kbName` is empty or longer than 255 characters
- `kbName` fails XSS or format-specifier validation in the gateway controller
- Invalid JSON request body at the connector (`Invalid request body`)
- Connector rejected the update payload
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Unauthorized — valid bearer token required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: |
Forbidden. Possible reasons:
- OAuth token lacks the `kb:write` scope
- User has no permission on this knowledge base
- User role is insufficient (`READER`; requires `OWNER` or `WRITER`)
- Connector service denied the request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: |
Not found. Possible reasons:
- Knowledge base does not exist
- Authenticated user does not exist in the graph database
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal server error — updating knowledge base failed in connector or database
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'503':
description: Service unavailable — connector service is unreachable
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
delete:
tags:
- Knowledge Base
summary: Delete knowledge base
description: |
Permanently delete a knowledge base and all its contents.
**Required permission:**
User must have `OWNER` role on the knowledge base.
**What gets deleted:**
- All folders within the KB
- All records and their indexed content
- All permission grants
- Associated storage files
**Warning:** This action is irreversible. Consider exporting data before deletion.
operationId: deleteKnowledgeBase
security:
- bearerAuth: []
- oauth2:
- kb:delete
parameters:
- name: kbId
in: path
required: true
description: Knowledge base ID (non-empty string)
schema:
type: string
minLength: 1
example: 8a095180-2989-4018-b448-70eb75fba1c7
responses:
'200':
description: Knowledge base deleted successfully
content:
application/json:
schema:
$ref: '#/components/schemas/DeleteKnowledgeBaseById'
'401':
description: Unauthorized — valid bearer token required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: |
Forbidden. Possible reasons:
- OAuth token lacks the `kb:delete` scope
- User has no permission on this knowledge base
- User is not `OWNER` (only KB owners can delete)
- Connector service denied the request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: |
Not found. Possible reasons:
- Knowledge base does not exist
- Authenticated user does not exist in the graph database
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal server error — deleting knowledge base failed in connector or database
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'503':
description: Service unavailable — connector service is unreachable
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/knowledgeBase/record/{recordId}:
get:
tags:
- Knowledge Base
summary: Get record by ID
description: |
Retrieve detailed information about a specific record.
**Overview:**
Returns complete record metadata including name, type, indexing status, storage information, and version history.
**File conversion:**
Use the optional `convertTo` parameter to request file format conversion (e.g., PDF to text). Supported conversions include PPT to PDF and PPTX to PDF.
operationId: getRecordById
security:
- bearerAuth: []
- oauth2:
- kb:read
parameters:
- name: recordId
in: path
required: true
description: Record ID
schema:
type: string
- name: convertTo
in: query
description: Optional format to convert the file to (e.g., PDF to text). Supported conversions include PPT to PDF and PPTX to PDF.
schema:
type: string
example: txt
responses:
'200':
description: Successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/GetRecordByIdResponseSchema'
'400':
description: Invalid request parameters or query shape
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Missing, invalid, expired, or revoked authentication
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: OAuth token is missing the required kb:read scope
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Record not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: |
Internal server error while retrieving record details.
Current API behavior includes record-access lookup failures returning
`HTTP_INTERNAL_SERVER_ERROR` with messages such as
`Failed to check record access`, including cases where callers might
otherwise expect a not-found style response.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'503':
description: Connector service unavailable or connection refused
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
put:
tags:
- Knowledge Base
summary: Update record
description: |
Update a record's name and/or file content.
**Overview:**
Allows updating the display name and optionally replacing the file content. Triggers re-indexing when content changes.
**Required permission:**
WRITER or higher
**Updating file content:**
Include a new file in the request to replace the existing content. The file extension must match the original.
**Side effects:**
- Updates `updatedAtTimestamp`
- Increments version if file content changed
- Triggers re-indexing for content changes
operationId: updateRecord
security:
- bearerAuth: []
- oauth2:
- kb:write
parameters:
- name: recordId
in: path
required: true
description: Record ID
schema:
type: string
requestBody:
description: Request payload
content:
multipart/form-data:
schema:
type: object
properties:
recordName:
type: string
description: New name for the record
maxLength: 255
file:
type: string
format: binary
description: Replacement file content
responses:
'200':
description: Record updated successfully
content:
application/json:
schema:
allOf:
- type: object
properties:
success:
type: boolean
message:
type: string
record:
$ref: '#/components/schemas/Record'
- $ref: '#/components/schemas/UpdateRecordEnrichment'
'400':
description: Invalid request parameters
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Missing, invalid, expired, or revoked authentication
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: OAuth token is missing the required kb:write scope
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Record not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal server error while updating record
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'503':
description: Connector service unavailable or connection refused
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
delete:
tags:
- Knowledge Base
summary: Delete record
description: |
Permanently delete a record from the knowledge base.
**Required permission:**
WRITER or higher
**What gets deleted:**
- Record metadata
- Associated storage file
- Indexed content and embeddings
**Warning:** This action is irreversible.
operationId: deleteRecord
security:
- bearerAuth: []
- oauth2:
- kb:delete
parameters:
- name: recordId
in: path
required: true
description: Record ID
schema:
type: string
responses:
'200':
description: Record deleted successfully
content:
application/json:
schema:
$ref: '#/components/schemas/DeleteRecordResponseSchema'
'400':
description: Invalid request parameters
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Missing, invalid, expired, or revoked authentication
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: OAuth token is missing the required kb:delete scope
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Record not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal server error while deleting record
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'503':
description: Connector service unavailable or connection refused
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/knowledgeBase/stream/record/{recordId}:
get:
tags:
- Knowledge Base
summary: Stream record content
description: |
Stream the binary content of a record's file.
**Overview:**
Returns the raw file content with appropriate `Content-Type` and `Content-Disposition` headers for download or inline viewing.
**Use cases:**
- File downloads
- Inline document preview
- Content extraction pipelines
**Format conversion:**
Use the `convertTo` parameter to convert between formats (e.g. DOCX to PDF).
operationId: streamRecordBuffer
security:
- bearerAuth: []
- oauth2:
- kb:read
parameters:
- name: recordId
in: path
required: true
description: Record ID
schema:
type: string
- name: convertTo
in: query
description: Target format for conversion
schema:
type: string
responses:
'200':
description: File content stream
content:
'*/*':
schema:
type: string
format: binary
'400':
description: Invalid record ID or query parameters
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Missing, invalid, expired, or revoked authentication
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: |
Forbidden. Returned either when the OAuth token is missing the required
`kb:read` scope or when the authenticated user does not have access to the record.
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/ErrorResponse'
- $ref: '#/components/schemas/StreamRecordErrorResponse'
'404':
description: Record, organization, or backing connector not found
content:
application/json:
schema:
$ref: '#/components/schemas/StreamRecordErrorResponse'
'409':
description: |
Conflict - the connector instance for this record is disabled. Enable it from Connector Settings and try again.
content:
application/json:
schema:
$ref: '#/components/schemas/StreamRecordErrorResponse'
'500':
description: |
Internal streaming failure, downstream conversion failure, or connector/backend
error proxied by the gateway.
content:
application/json:
schema:
$ref: '#/components/schemas/StreamRecordErrorResponse'
/knowledgeBase/{kbId}/folder:
post:
tags:
- Knowledge Base
summary: Create folder
description: |
Create a folder in a knowledge base. Omit `folderId` to create at the KB root;
pass `folderId` as a query parameter to create a nested subfolder inside an
existing parent folder.
**Required permission:** WRITER or higher
**Folder features:**
- Organize records hierarchically
- Support nested subfolders (unlimited depth)
- Inherit parent KB permissions
**Naming rules:**
- 1–255 characters
- XSS protection applied
- Spaces and special characters allowed
- Duplicate names rejected within the same parent (`409`)
**Response:** Returns `id` and `name` for the created folder.
operationId: createFolder
security:
- bearerAuth: []
- oauth2:
- kb:write
parameters:
- name: kbId
in: path
required: true
description: Knowledge base ID
schema:
type: string
- name: folderId
in: query
required: false
description: Parent folder ID. Omit to create at the knowledge base root.
schema:
type: string
requestBody:
required: true
description: Request payload
content:
application/json:
schema:
type: object
properties:
folderName:
type: string
minLength: 1
maxLength: 255
description: Name of the folder
example: Project Documents
required:
- folderName
responses:
'200':
description: Folder created successfully
content:
application/json:
schema:
$ref: '#/components/schemas/FolderCreateResponseSchema'
'400':
description: |
Invalid request. Possible reasons:
- Missing or empty folder name
- Folder name exceeds 255 characters
- XSS or invalid characters in folder name
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Unauthorized - Valid bearer token required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: |
Forbidden. Possible reasons:
- OAuth token lacks the `kb:write` scope
- User lacks WRITER or higher permission on the knowledge base
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Knowledge base or parent folder not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'409':
description: Folder with this name already exists at the knowledge base root or within the parent folder
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal server error while creating folder
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'503':
description: Connector service unavailable or connection refused
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/knowledgeBase/{kbId}/folder/{folderId}:
put:
tags:
- Knowledge Base
summary: Update folder
description: |
Rename a folder.
**Required permission:** WRITER or higher
operationId: updateFolder
security:
- bearerAuth: []
- oauth2:
- kb:write
parameters:
- name: kbId
in: path
required: true
schema:
type: string
- name: folderId
in: path
required: true
schema:
type: string
requestBody:
required: true
description: Request payload
content:
application/json:
schema:
type: object
properties:
folderName:
type: string
minLength: 1
maxLength: 255
required:
- folderName
responses:
'200':
description: Folder updated successfully
content:
application/json:
schema:
$ref: '#/components/schemas/FolderUpdateResponseSchema'
'400':
description: |
Invalid request. Possible reasons:
- Missing or empty folder name
- Folder name exceeds 255 characters
- XSS or invalid characters in folder name
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Unauthorized - Valid bearer token required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: |
Forbidden. Possible reasons:
- OAuth token lacks the `kb:write` scope
- User lacks WRITER or higher permission on the knowledge base
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Knowledge base or folder not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'409':
description: Folder with this name already exists at the knowledge base root
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal server error while updating folder
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'503':
description: Connector service unavailable or connection refused
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
delete:
tags:
- Knowledge Base
summary: Delete folder
description: |
Delete a folder and all its contents.
**Required permission:** WRITER or higher
**Cascade delete:**
All subfolders and records within will be permanently deleted.
**Warning:** This action is irreversible.
operationId: deleteFolder
security:
- bearerAuth: []
- oauth2:
- kb:delete
parameters:
- name: kbId
in: path
required: true
schema:
type: string
- name: folderId
in: path
required: true
schema:
type: string
responses:
'200':
description: Folder deleted successfully
content:
application/json:
schema:
$ref: '#/components/schemas/FolderDeleteResponseSchema'
'400':
description: Invalid request parameters
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Unauthorized - Valid bearer token required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: |
Forbidden. Possible reasons:
- OAuth token lacks the `kb:delete` scope
- User lacks OWNER permission on the knowledge base
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Knowledge base or folder not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/knowledgeBase/{kbId}/upload:
post:
tags:
- Knowledge Base
summary: Upload files to knowledge base or folder
description: |
Upload one or more files to a knowledge base root or to a specific folder.
**Overview**
Batch upload multiple files in a single request. Each file becomes a new record with automatic content indexing.
Omit the `folderId` query parameter to upload to the KB root; include it to upload into that folder.
**Upload Limits**
- **Max files per request:** 1000
- **Default max file size:** 30MB (configurable via platform settings)
- Use `GET /knowledgeBase/limits` to check current limits
**Supported File Types**
Documents (PDF, DOCX, DOC, XLS, XLSX, PPT, PPTX, TXT, CSV, MD), Images (PNG, JPG, JPEG, SVG, WebP), Web (HTML, HTM), and Google Workspace formats.
**File Metadata**
Use `files_metadata` to provide additional info like file paths and last modified timestamps.
**Versioning**
Set `isVersioned: true` to enable version tracking for uploaded files.
**Streaming response**
This endpoint responds with `Content-Type: text/event-stream`.
The upload and its per-file progress are a single request: the body streams
a `file:succeeded` or `file:failed` event per file
(including files rejected up front for size/type), followed by a final
`done` summary, then closes. See the
`UploadStreamSSEEvent` schema for the event/payload contract.
operationId: uploadRecords
security:
- bearerAuth: []
- oauth2:
- kb:upload
parameters:
- name: kbId
in: path
required: true
description: Knowledge base ID
schema:
type: string
- name: folderId
in: query
required: false
description: Target folder ID. Omit to upload to the KB root.
schema:
type: string
requestBody:
required: true
description: Request payload
content:
multipart/form-data:
schema:
type: object
properties:
files:
type: array
items:
type: string
format: binary
description: Files to upload (max 1000)
files_metadata:
type: string
description: JSON array with file_path and last_modified for each file
example: '[{"file_path":"/docs/report.pdf","last_modified":"2024-01-15T10:30:00Z"}]'
isVersioned:
type: boolean
default: true
description: Enable version tracking
recordType:
type: string
default: FILE
description: Type of records to create
required:
- files
responses:
'200':
description: |
SSE stream (`text/event-stream`) of per-file upload outcomes. The
stream emits `file:succeeded` / `file:failed` per file and a final
`done` summary, then closes. See `UploadStreamSSEEvent`.
content:
text/event-stream:
schema:
$ref: '#/components/schemas/UploadStreamSSEEvent'
'400':
description: Invalid request - Check file types and sizes
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Insufficient permissions (requires WRITER or higher)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Knowledge base or folder not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'413':
description: File size exceeds maximum allowed
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'429':
description: Too many upload requests, or too many concurrent uploads for this user
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Failed to verify knowledge base or folder access
content:
schema:
$ref: '#/components/schemas/ErrorResponse'
/knowledgeBase/limits:
get:
tags:
- Knowledge Base
summary: Get knowledge base upload limits
description: |
Retrieve current upload constraints for the organization.
**Use case:** Call this before uploads to validate file sizes on the client
side and display appropriate limits to users.
operationId: getUploadLimits
security:
- bearerAuth: []
- oauth2:
- kb:read
responses:
'200':
description: Upload limits retrieved
content:
application/json:
schema:
$ref: '#/components/schemas/UploadLimitsResponseSchema'
'401':
description: Unauthorized - Valid bearer token required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/knowledgeBase/reindex/record/{recordId}:
post:
tags:
- Knowledge Base
summary: Reindex single record
description: |
Trigger reindexing for a specific record.
**Overview:**
Reprocesses the record's content to update search indexes and AI embeddings. Useful after content changes or to fix indexing failures.
**Depth parameter:**
Controls processing depth for complex documents (`-1` for full depth, `0`–`100` for limited).
**Status filters:**
Optional `statusFilters` array limits reindex to records in matching indexing states
(e.g. `FAILED`, `AUTO_INDEX_OFF`).
operationId: reindexRecord
security:
- bearerAuth: []
- oauth2:
- kb:write
parameters:
- name: recordId
in: path
required: true
schema:
type: string
requestBody:
description: Request payload
content:
application/json:
schema:
$ref: '#/components/schemas/ReindexRecordRequestBody'
responses:
'200':
description: Reindexing triggered successfully
content:
application/json:
schema:
$ref: '#/components/schemas/reIndexRecordResponseSchema'
'400':
description: Invalid request body or parameters
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Missing, invalid, expired, or revoked authentication
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: OAuth token is missing the required kb:write scope
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Record not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'409':
description: Conflict — the connector instance for this record is disabled. Enable it from Connector Settings and try again.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal server error while reindexing the record
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'503':
description: Connector service unavailable or connection refused
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/knowledgeBase/reindex/record-group/{recordGroupId}:
post:
tags:
- Knowledge Base
summary: Reindex record group
description: |
Trigger reindexing for all records in a folder or knowledge base.
**Overview:**
Batch reindex operation for entire containers. The `recordGroupId` can be a folder ID or KB ID.
**Status filters:**
Optional `statusFilters` limit which child records are queued (e.g. failed-only or manual-indexing).
operationId: reindexRecordGroup
security:
- bearerAuth: []
- oauth2:
- kb:write
parameters:
- name: recordGroupId
in: path
required: true
description: Folder ID or KB ID
schema:
type: string
requestBody:
description: Request payload
content:
application/json:
schema:
$ref: '#/components/schemas/ReindexRecordGroupRequestBody'
responses:
'200':
description: Reindexing triggered for all records in group
content:
application/json:
schema:
$ref: '#/components/schemas/ReIndexRecordGroupResponseSchema'
'400':
description: Invalid request body or parameters
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Missing, invalid, expired, or revoked authentication
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: OAuth token is missing the required kb:write scope
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Record group not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'409':
description: Conflict - the connector instance is disabled. Enable it from Connector Settings and try again.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal server error while reindexing the record group
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'503':
description: Connector service unavailable or connection refused
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/knowledgeBase/{kbId}/record/{recordId}/move:
put:
tags:
- Knowledge Base
summary: Move record to another location
description: |
Move a file or folder record to a different location within the same knowledge base.
Set `newParentId` to a folder ID to move the record into that folder, or `null` to move it to the knowledge base root.
**Required Permission:** OWNER or WRITER
operationId: moveRecord
security:
- bearerAuth: []
- oauth2:
- kb:write
parameters:
- name: kbId
in: path
required: true
schema:
type: string
format: uuid
description: Knowledge base UUID
- name: recordId
in: path
required: true
schema:
type: string
minLength: 1
description: Record identifier (file or folder)
requestBody:
required: true
description: Target location for the record
content:
application/json:
schema:
$ref: '#/components/schemas/KnowledgeBaseMoveRecordRequestBody'
responses:
'200':
description: Record moved successfully
content:
application/json:
schema:
$ref: '#/components/schemas/KnowledgeBaseMoveRecordResponse'
'400':
description: |
Invalid request. Possible reasons:
- Missing `newParentId` in the request body
- Invalid `kbId` (must be a UUID)
- Empty `recordId`
- Cannot move a folder into itself
- Cannot move a folder into one of its own sub-folders (circular reference)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Unauthorized - Valid bearer token required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: |
Forbidden. Possible reasons:
- OAuth token lacks the `kb:write` scope
- User lacks OWNER or WRITER permission on the knowledge base
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: |
Not found. Possible reasons:
- Knowledge base does not exist
- Record does not exist in the knowledge base
- Target folder does not exist in the knowledge base
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal server error while moving record
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'503':
description: Connector service unavailable or connection refused
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/knowledgeBase/knowledge-hub/nodes:
get:
deprecated: true
x-speakeasy-deprecation-message: Use the Knowledge Base API instead. This grouping will be removed in a future release
tags:
- Knowledge Base
- Knowledge Hub
summary: Get knowledge hub root nodes
description: |
Returns root-level nodes (connector apps and Collection apps) or, when
filters or search are applied, a flat list of matching nodes across the
entire knowledge hub tree.
**Overview**
The Knowledge Hub provides a unified view across all knowledge sources:
- **Collection** — locally uploaded knowledge bases (`origin: COLLECTION`)
- **Connector app** — external connector instances such as Google Drive,
Slack, Confluence, Jira (`origin: CONNECTOR`)
Use this endpoint to build file-browser UIs and sidebar navigation trees.
**Browsing vs. searching**
When no filters or search query are provided, only top-level app nodes
are returned. Adding `nodeTypes`, `q`, or other filter params triggers a
search across the full tree, returning matching nodes regardless of depth.
For children of a specific node, use
`GET /knowledgeBase/knowledge-hub/nodes/{parentType}/{parentId}`.
**Pagination and sorting**
Results are always paginated. Default sort is `updatedAt` descending.
The `pagination` object in the response contains `hasNext` / `hasPrev`
flags suitable for infinite-scroll or page-based navigation.
**Expanding the response**
Use the `include` parameter to request additional sections:
- `availableFilters` — adds `filters.available` with all filter options
- `counts` — adds a `counts` summary broken down by node type
- `breadcrumbs` — adds the breadcrumb trail (empty at root level)
- `permissions` — adds the caller's permission flags
**Access control**
Requires a valid bearer token. For OAuth tokens the `kb:read` scope
must be present; regular JWT bearer tokens pass through without scope
enforcement.
operationId: getKnowledgeHubRootNodes
security:
- bearerAuth: []
- oauth2:
- kb:read
parameters:
- name: onlyContainers
in: query
required: false
description: |
When `true`, only nodes that have children are returned (useful for
building sidebar / tree navigation). Leaf nodes are excluded.
schema:
type: boolean
default: false
- name: page
in: query
required: false
description: |
Page number (1-indexed). Combined with `limit` to paginate results.
schema:
type: integer
minimum: 1
default: 1
- name: limit
in: query
required: false
description: |
Maximum number of items to return per page.
schema:
type: integer
minimum: 1
maximum: 200
default: 50
- name: sortBy
in: query
required: false
description: |
Field to sort results by. Omitted → default `updatedAt`.
Unknown value → silently falls back to `name`.
schema:
type: string
enum:
- name
- createdAt
- updatedAt
- size
- type
default: updatedAt
- name: sortOrder
in: query
required: false
description: |
Sort direction. Omitted → default `desc`.
Unknown value → silently falls back to `asc`.
schema:
type: string
enum:
- asc
- desc
default: desc
- name: q
in: query
required: false
description: |
Full-text search query. Must be between 2 and 500 characters
(inclusive). When provided, the endpoint searches across the entire
node tree regardless of the current browse level.
schema:
type: string
minLength: 2
maxLength: 500
example: quarterly report
- name: nodeTypes
in: query
required: false
description: |
Comma-separated list of node types to include. Invalid values are
silently ignored. Maximum 100 items.
Valid values: `folder`, `app`, `recordGroup`, `record`
schema:
type: string
example: app,recordGroup
- name: recordTypes
in: query
required: false
description: |
Comma-separated list of record types to include. Invalid values are
silently ignored. Maximum 100 items.
Valid values: `FILE`, `DRIVE`, `WEBPAGE`, `DATABASE`, `DATASOURCE`,
`MESSAGE`, `MAIL`, `GROUP_MAIL`, `TICKET`, `COMMENT`,
`INLINE_COMMENT`, `CONFLUENCE_PAGE`, `CONFLUENCE_BLOGPOST`,
`SHAREPOINT_PAGE`, `SHAREPOINT_LIST`, `SHAREPOINT_LIST_ITEM`,
`SHAREPOINT_DOCUMENT_LIBRARY`, `LINK`, `PROJECT`, `PULL_REQUEST`,
`MEETING`, `PRODUCT`, `DEAL`, `CASE`, `TASK`, `ARTIFACT`,
`CODE_FILE`, `SQL_TABLE`, `SQL_VIEW`, `OTHERS`
schema:
type: string
example: FILE,CONFLUENCE_PAGE
- name: origins
in: query
required: false
description: |
Comma-separated list of origin types to include. Invalid values are
silently ignored. Maximum 100 items.
Valid values: `COLLECTION`, `CONNECTOR`
schema:
type: string
example: CONNECTOR
- name: connectorIds
in: query
required: false
description: |
Comma-separated list of connector instance IDs (UUIDs) to filter by.
Maximum 100 items. No enum validation — any string is accepted, but
non-existent IDs simply yield zero results.
schema:
type: string
example: f3a4b5b6-5b6c-4e85-9097-3202cfe696fc
- name: indexingStatus
in: query
required: false
description: |
Comma-separated list of indexing statuses to include. Invalid values
are silently ignored. Maximum 100 items.
Valid values: `NOT_STARTED`, `PAUSED`, `IN_PROGRESS`, `COMPLETED`,
`FAILED`, `FILE_TYPE_NOT_SUPPORTED`, `AUTO_INDEX_OFF`, `EMPTY`,
`ENABLE_MULTIMODAL_MODELS`, `QUEUED`
schema:
type: string
example: COMPLETED,FAILED
- name: createdAt
in: query
required: false
description: |
Created-date range filter. Format: `gte:,lte:`.
Both bounds are optional (you may send just `gte:...` or just
`lte:...`). Timestamps must be in the range 0 to 9999999999999 and
`gte` must be less than or equal to `lte` when both are present.
schema:
type: string
example: gte:1700000000000,lte:1710000000000
- name: updatedAt
in: query
required: false
description: |
Updated-date range filter. Same format and constraints as `createdAt`.
schema:
type: string
example: gte:1700000000000,lte:1710000000000
- name: size
in: query
required: false
description: |
File-size range filter in bytes. Format: `gte:,lte:`.
Both bounds are optional. Values must be non-negative and at most
1099511627776 (1 TB). `gte` must be less than or equal to `lte`
when both are present.
schema:
type: string
example: gte:0,lte:10485760
- name: include
in: query
required: false
description: |
Comma-separated list of additional response sections to include.
Invalid values are silently ignored. Maximum 100 items.
Valid values: `breadcrumbs`, `counts`, `availableFilters`, `permissions`
schema:
type: string
example: availableFilters,counts
responses:
'200':
description: |
Paginated list of root hub nodes (connector apps and Collections).
HTTP 200 returns `success: true` and `error: null`. Field-level detail
and required keys are defined on `KnowledgeHubNodesResponse`.
Use `include` for optional sections: `availableFilters`, `counts`,
`permissions` — each stays JSON `null` when not asked for.
`breadcrumbs` stays `null` at this route (no parent in the path),
even if `include` lists `breadcrumbs`; use the child route for trails.
`id`, `currentNode`, and `parentNode` are `null` here.
content:
application/json:
schema:
$ref: '#/components/schemas/KnowledgeHubNodesResponse'
examples:
root_apps:
summary: Root-level apps with availableFilters included
value:
success: true
error: null
id: null
currentNode: null
parentNode: null
items:
- id: knowledgeBase_org123
name: Collections
nodeType: app
parentId: null
origin: COLLECTION
connector: null
recordType: null
recordGroupType: null
indexingStatus: null
reason: null
createdAt: 1700000000000
updatedAt: 1710000000000
sizeInBytes: null
mimeType: null
extension: null
webUrl: /app/knowledgeBase_org123
hasChildren: true
previewRenderable: null
permission: null
sharingStatus: workspace
isInternal: false
- id: f3a4b5b6-5b6c-4e85-9097-3202cfe696fc
name: Google Drive
nodeType: app
parentId: null
origin: CONNECTOR
connector: drive
recordType: null
recordGroupType: null
indexingStatus: null
reason: null
createdAt: 1700000000000
updatedAt: 1709000000000
sizeInBytes: null
mimeType: null
extension: null
webUrl: /app/f3a4b5b6-5b6c-4e85-9097-3202cfe696fc
hasChildren: true
previewRenderable: null
permission: null
sharingStatus: null
isInternal: false
pagination:
page: 1
limit: 20
totalItems: 2
totalPages: 1
hasNext: false
hasPrev: false
filters:
applied:
q: null
nodeTypes: null
recordTypes: null
origins: null
connectorIds: null
indexingStatus: null
createdAt: null
updatedAt: null
size: null
sortBy: updatedAt
sortOrder: desc
available:
nodeTypes:
- id: app
label: Apps
- id: recordGroup
label: Record Groups
recordTypes: []
origins:
- id: COLLECTION
label: Collection
- id: CONNECTOR
label: Connector
connectors:
- id: f3a4b5b6-5b6c-4e85-9097-3202cfe696fc
label: Google Drive
connectorType: drive
indexingStatus: []
sortBy:
- id: name
label: Name
- id: updatedAt
label: Updated
sortOrder:
- id: asc
label: Ascending
- id: desc
label: Descending
breadcrumbs: null
counts: null
permissions: null
'400':
description: |
Invalid request parameters. The backend's validation message is
returned verbatim in `error.message`. See the examples below for
the common triggers.
content:
application/json:
schema:
type: object
required:
- error
properties:
error:
type: object
required:
- code
- message
properties:
code:
type: string
enum:
- HTTP_BAD_REQUEST
example: HTTP_BAD_REQUEST
message:
type: string
example: Search query must be at least 2 characters
examples:
query_too_short:
summary: Search query shorter than 2 characters
value:
error:
code: HTTP_BAD_REQUEST
message: Search query must be at least 2 characters
comma_list_too_long:
summary: Comma-separated parameter exceeds 100 items
value:
error:
code: HTTP_BAD_REQUEST
message: 'Too many items in comma-separated list (max: 100, got: 142)'
date_range_inverted:
summary: Date range with gte > lte
value:
error:
code: HTTP_BAD_REQUEST
message: 'Date range invalid: gte must be <= lte'
size_exceeds_max:
summary: Size filter exceeds the 1 TB cap
value:
error:
code: HTTP_BAD_REQUEST
message: 'Size exceeds maximum (1TB): 2199023255552'
'401':
description: |
Missing or invalid authentication token.
The bearer token was absent, expired, malformed, or could not be
verified by the auth middleware.
content:
application/json:
schema:
type: object
required:
- error
properties:
error:
type: object
required:
- code
- message
properties:
code:
type: string
enum:
- HTTP_UNAUTHORIZED
example: HTTP_UNAUTHORIZED
message:
type: string
example: Invalid token
example:
error:
code: HTTP_UNAUTHORIZED
message: Invalid token
'403':
description: |
Insufficient OAuth scope.
Only applies to OAuth tokens. The token did not carry the `kb:read`
scope required by this endpoint. Regular (non-OAuth) JWT bearer
tokens are not subject to scope enforcement and will not receive
this error.
content:
application/json:
schema:
type: object
required:
- error
properties:
error:
type: object
required:
- code
- message
properties:
code:
type: string
enum:
- HTTP_FORBIDDEN
example: HTTP_FORBIDDEN
message:
type: string
example: 'Insufficient scope. Required: kb:read'
example:
error:
code: HTTP_FORBIDDEN
message: 'Insufficient scope. Required: kb:read'
'500':
description: An unexpected error occurred on the server.
content:
application/json:
schema:
type: object
required:
- error
properties:
error:
type: object
required:
- code
- message
properties:
code:
type: string
enum:
- HTTP_INTERNAL_SERVER_ERROR
example: HTTP_INTERNAL_SERVER_ERROR
message:
type: string
example: An unexpected error occurred
example:
error:
code: HTTP_INTERNAL_SERVER_ERROR
message: An unexpected error occurred
/knowledgeBase/knowledge-hub/nodes/{parentType}/{parentId}:
get:
deprecated: true
x-speakeasy-deprecation-message: Use the Knowledge Base API instead. This grouping will be removed in a future release
tags:
- Knowledge Base
- Knowledge Hub
summary: Get knowledge hub child nodes
description: |
Returns the children of a specific node in the knowledge hub tree.
Use this endpoint to drill down into Collections, connector app
hierarchies, folders, and record groups.
**Navigation hierarchy**
The typical drill-down path is:
1. Root apps (`GET /knowledgeBase/knowledge-hub/nodes`)
2. Record groups / folders within an app (`parentType=app`)
3. Records within a record group (`parentType=recordGroup`)
4. Sub-records or attachments within a record (`parentType=record`)
**Parent identification**
- `parentType` must be one of: `app`, `recordGroup`, `folder`, `record`
- `parentId` is either a standard UUID or the Collection app sentinel
`knowledgeBase_` (e.g. `knowledgeBase_org123`)
**Filtering and searching**
All query-param filters from the root endpoint are available here and
operate within the scope of the parent node's subtree. When `q` is
provided, the search spans all descendants of the parent node.
**Response extras**
When `include=breadcrumbs` is set, the response contains a
`breadcrumbs` array tracing the path from the root to the current
node. The `currentNode` and `parentNode` objects are always populated
for non-root requests.
**Access control**
Requires a valid bearer token. For OAuth tokens the `kb:read` scope
must be present; regular JWT bearer tokens pass through without scope
enforcement.
operationId: getKnowledgeHubChildNodes
security:
- bearerAuth: []
- oauth2:
- kb:read
parameters:
- name: parentType
in: path
required: true
description: |
Type of the parent node whose children to retrieve.
Must be one of: `app`, `recordGroup`, `folder`, `record`.
Any other value returns a 400 error.
schema:
type: string
enum:
- app
- recordGroup
- folder
- record
- name: parentId
in: path
required: true
description: |
Identifier of the parent node. Accepts two formats:
- A standard UUID (e.g. `f3a4b5b6-5b6c-4e85-9097-3202cfe696fc`)
- The Collection app sentinel `knowledgeBase_`
(e.g. `knowledgeBase_org123`)
Any value that does not match either format returns a 400 error.
schema:
type: string
pattern: ^(knowledgeBase_[a-zA-Z0-9_-]+|[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})$
- name: onlyContainers
in: query
required: false
description: |
When `true`, only nodes that have children are returned (useful for
building sidebar / tree navigation). Leaf nodes are excluded.
schema:
type: boolean
default: false
- name: page
in: query
required: false
description: |
Page number (1-indexed). Combined with `limit` to paginate results.
schema:
type: integer
minimum: 1
default: 1
- name: limit
in: query
required: false
description: |
Maximum number of items to return per page.
schema:
type: integer
minimum: 1
maximum: 200
default: 50
- name: sortBy
in: query
required: false
description: |
Field to sort results by. Omitted → default `updatedAt`.
Unknown value → silently falls back to `name`.
schema:
type: string
enum:
- name
- createdAt
- updatedAt
- size
- type
default: updatedAt
- name: sortOrder
in: query
required: false
description: |
Sort direction. Omitted → default `desc`.
Unknown value → silently falls back to `asc`.
schema:
type: string
enum:
- asc
- desc
default: desc
- name: q
in: query
required: false
description: |
Full-text search query. Must be between 2 and 500 characters
(inclusive). When provided, the endpoint searches across all
descendants of the parent node.
schema:
type: string
minLength: 2
maxLength: 500
example: quarterly report
- name: nodeTypes
in: query
required: false
description: |
Comma-separated list of node types to include. Invalid values are
silently ignored. Maximum 100 items.
Valid values: `folder`, `app`, `recordGroup`, `record`
schema:
type: string
example: recordGroup
- name: recordTypes
in: query
required: false
description: |
Comma-separated list of record types to include. Invalid values are
silently ignored. Maximum 100 items.
Valid values: `FILE`, `DRIVE`, `WEBPAGE`, `DATABASE`, `DATASOURCE`,
`MESSAGE`, `MAIL`, `GROUP_MAIL`, `TICKET`, `COMMENT`,
`INLINE_COMMENT`, `CONFLUENCE_PAGE`, `CONFLUENCE_BLOGPOST`,
`SHAREPOINT_PAGE`, `SHAREPOINT_LIST`, `SHAREPOINT_LIST_ITEM`,
`SHAREPOINT_DOCUMENT_LIBRARY`, `LINK`, `PROJECT`, `PULL_REQUEST`,
`MEETING`, `PRODUCT`, `DEAL`, `CASE`, `TASK`, `ARTIFACT`,
`CODE_FILE`, `SQL_TABLE`, `SQL_VIEW`, `OTHERS`
schema:
type: string
example: FILE,CONFLUENCE_PAGE
- name: origins
in: query
required: false
description: |
Comma-separated list of origin types to include. Invalid values are
silently ignored. Maximum 100 items.
Valid values: `COLLECTION`, `CONNECTOR`
schema:
type: string
example: CONNECTOR
- name: connectorIds
in: query
required: false
description: |
Comma-separated list of connector instance IDs (UUIDs) to filter by.
Maximum 100 items. No enum validation — any string is accepted, but
non-existent IDs simply yield zero results.
schema:
type: string
example: f3a4b5b6-5b6c-4e85-9097-3202cfe696fc
- name: indexingStatus
in: query
required: false
description: |
Comma-separated list of indexing statuses to include. Invalid values
are silently ignored. Maximum 100 items.
Valid values: `NOT_STARTED`, `PAUSED`, `IN_PROGRESS`, `COMPLETED`,
`FAILED`, `FILE_TYPE_NOT_SUPPORTED`, `AUTO_INDEX_OFF`, `EMPTY`,
`ENABLE_MULTIMODAL_MODELS`, `QUEUED`
schema:
type: string
example: COMPLETED,FAILED
- name: createdAt
in: query
required: false
description: |
Created-date range filter. Format: `gte:,lte:`.
Both bounds are optional (you may send just `gte:...` or just
`lte:...`). Timestamps must be in the range 0 to 9999999999999 and
`gte` must be less than or equal to `lte` when both are present.
schema:
type: string
example: gte:1700000000000,lte:1710000000000
- name: updatedAt
in: query
required: false
description: |
Updated-date range filter. Same format and constraints as `createdAt`.
schema:
type: string
example: gte:1700000000000,lte:1710000000000
- name: size
in: query
required: false
description: |
File-size range filter in bytes. Format: `gte:,lte:`.
Both bounds are optional. Values must be non-negative and at most
1099511627776 (1 TB). `gte` must be less than or equal to `lte`
when both are present.
schema:
type: string
example: gte:0,lte:10485760
- name: include
in: query
required: false
description: |
Comma-separated list of additional response sections to include.
Invalid values are silently ignored. Maximum 100 items.
Valid values: `breadcrumbs`, `counts`, `availableFilters`, `permissions`
schema:
type: string
example: breadcrumbs,availableFilters
responses:
'200':
description: |
Paginated children of `{parentType}/{parentId}`. HTTP 200 returns
`success: true` and `error: null`; see `KnowledgeHubNodesResponse` for
the full shape.
`id` and `currentNode` reflect the parent being browsed; `parentNode`
is set when a grandparent exists. Optional sections (`availableFilters`,
`counts`, `permissions`, `breadcrumbs`) are JSON `null` unless listed
in `include` and populated by the server.
content:
application/json:
schema:
$ref: '#/components/schemas/KnowledgeHubNodesResponse'
examples:
collection_record_groups:
summary: Record groups inside the Collection app with breadcrumbs
value:
success: true
error: null
id: knowledgeBase_org123
currentNode:
id: knowledgeBase_org123
name: Collections
nodeType: app
subType: null
parentNode: null
items:
- id: a1b2c3d4-e5f6-7890-abcd-ef1234567890
name: Engineering Docs
nodeType: recordGroup
parentId: knowledgeBase_org123
origin: COLLECTION
connector: null
recordType: null
recordGroupType: KNOWLEDGE_BASE
indexingStatus: null
reason: null
createdAt: 1700000000000
updatedAt: 1709500000000
sizeInBytes: null
mimeType: null
extension: null
webUrl: null
hasChildren: true
previewRenderable: null
permission: null
sharingStatus: workspace
isInternal: false
- id: b2c3d4e5-f6a7-8901-bcde-f12345678901
name: HR Policies
nodeType: recordGroup
parentId: knowledgeBase_org123
origin: COLLECTION
connector: null
recordType: null
recordGroupType: KNOWLEDGE_BASE
indexingStatus: null
reason: null
createdAt: 1700100000000
updatedAt: 1709400000000
sizeInBytes: null
mimeType: null
extension: null
webUrl: null
hasChildren: true
previewRenderable: null
permission: null
sharingStatus: private
isInternal: false
pagination:
page: 1
limit: 20
totalItems: 2
totalPages: 1
hasNext: false
hasPrev: false
filters:
applied:
q: null
nodeTypes:
- recordGroup
recordTypes: null
origins: null
connectorIds: null
indexingStatus: null
createdAt: null
updatedAt: null
size: null
sortBy: name
sortOrder: asc
available: null
breadcrumbs:
- id: knowledgeBase_org123
name: Collections
nodeType: app
subType: null
counts: null
permissions: null
'400':
description: |
Invalid request parameters or path values. The backend's validation
message is returned verbatim in `error.message`. See the examples
below for the common triggers.
content:
application/json:
schema:
type: object
required:
- error
properties:
error:
type: object
required:
- code
- message
properties:
code:
type: string
enum:
- HTTP_BAD_REQUEST
example: HTTP_BAD_REQUEST
message:
type: string
example: 'Invalid parent_type. Must be one of: app, recordGroup, folder, record'
examples:
invalid_parent_type:
summary: parentType outside the allowed set
value:
error:
code: HTTP_BAD_REQUEST
message: 'Invalid parent_type. Must be one of: app, recordGroup, folder, record'
invalid_parent_id:
summary: parentId is neither a UUID nor knowledgeBase_
value:
error:
code: HTTP_BAD_REQUEST
message: 'Invalid UUID format for parent_id: abc'
query_too_short:
summary: Search query shorter than 2 characters
value:
error:
code: HTTP_BAD_REQUEST
message: Search query must be at least 2 characters
comma_list_too_long:
summary: Comma-separated parameter exceeds 100 items
value:
error:
code: HTTP_BAD_REQUEST
message: 'Too many items in comma-separated list (max: 100, got: 142)'
date_range_inverted:
summary: Date range with gte > lte
value:
error:
code: HTTP_BAD_REQUEST
message: 'Date range invalid: gte must be <= lte'
'401':
description: |
Missing or invalid authentication token.
The bearer token was absent, expired, malformed, or could not be
verified by the auth middleware.
content:
application/json:
schema:
type: object
required:
- error
properties:
error:
type: object
required:
- code
- message
properties:
code:
type: string
enum:
- HTTP_UNAUTHORIZED
example: HTTP_UNAUTHORIZED
message:
type: string
example: Invalid token
example:
error:
code: HTTP_UNAUTHORIZED
message: Invalid token
'403':
description: |
Insufficient OAuth scope.
Only applies to OAuth tokens. The token did not carry the `kb:read`
scope required by this endpoint. Regular (non-OAuth) JWT bearer
tokens are not subject to scope enforcement and will not receive
this error.
content:
application/json:
schema:
type: object
required:
- error
properties:
error:
type: object
required:
- code
- message
properties:
code:
type: string
enum:
- HTTP_FORBIDDEN
example: HTTP_FORBIDDEN
message:
type: string
example: 'Insufficient scope. Required: kb:read'
example:
error:
code: HTTP_FORBIDDEN
message: 'Insufficient scope. Required: kb:read'
'404':
description: |
Parent node not found.
The `parentId` does not correspond to an existing node of the
specified `parentType`, or the node has been deleted.
content:
application/json:
schema:
type: object
required:
- error
properties:
error:
type: object
required:
- code
- message
properties:
code:
type: string
enum:
- HTTP_NOT_FOUND
example: HTTP_NOT_FOUND
message:
type: string
example: Parent node not found
example:
error:
code: HTTP_NOT_FOUND
message: Parent node not found
'500':
description: An unexpected error occurred on the server.
content:
application/json:
schema:
type: object
required:
- error
properties:
error:
type: object
required:
- code
- message
properties:
code:
type: string
enum:
- HTTP_INTERNAL_SERVER_ERROR
example: HTTP_INTERNAL_SERVER_ERROR
message:
type: string
example: An unexpected error occurred
example:
error:
code: HTTP_INTERNAL_SERVER_ERROR
message: An unexpected error occurred
/conversations/stream:
post:
tags:
- Conversations
summary: Create conversation with streaming response
description: |
Start a new conversation and stream the AI response over Server-Sent
Events (SSE). Behaves like `POST /conversations` but emits tokens,
tool activity, and status updates incrementally instead of returning
a single JSON response at the end.
**Lifecycle**
1. The server validates `query`, persists an in-progress
conversation, then opens the SSE stream with HTTP `200`.
2. A `connected` event is emitted immediately with the new
`conversationId` so the client can link the stream (sidebar,
parallel tabs, deep links) without an extra request.
3. AI-backend events stream through (token chunks, tool calls,
status, etc.).
4. On success a single `complete` event is emitted carrying the
full persisted conversation.
5. On failure an `error` event is emitted and the conversation is
marked FAILED before the stream closes.
**Event vocabulary**
Three events have stable, server-defined `data` shapes:
- `connected` — `{ "message": string, "conversationId": string,
"title": string }`
- `complete` — `{ "conversation": Conversation,
"meta": { "requestId": string, "timestamp": string,
"duration": number } }`
- `error` — `{ "error": string, "details"?: string }`
The forwarded events are `status`, `answer_chunk`, `tool_calls`,
`restreaming`, `metadata`, and `tool_execution_complete`. Their
payloads come from the Python query service and may evolve. Note
that raw `tool_call` / `tool_success` / `tool_error` / `tool_result`
events emitted by the LLM tool runtime are rewrapped as `status` by
the upstream wrapper before they reach this route, so clients on
`/conversations/stream` never see those names directly. Clients
should ignore unknown event names rather than treating them as
errors.
**Agent mode**
When `chatMode` selects an agent mode (for example `agent:auto`),
the optional `tools` list restricts which tools the agent may
invoke for this turn. Outside agent modes the `tools` field is
ignored.
operationId: streamChat
security:
- bearerAuth: []
- oauth2:
- conversation:chat
requestBody:
required: true
description: Request payload
content:
application/json:
schema:
$ref: '#/components/schemas/CreateConversationRequest'
responses:
'200':
description: |
SSE stream established. The body is a sequence of
`text/event-stream` frames using the event vocabulary described
above.
content:
text/event-stream:
schema:
$ref: '#/components/schemas/AssistantStreamSSEEvent'
'400':
description: |
Invalid request — `query` is missing, empty, or exceeds the
100000-character limit, or another field fails validation
(for example a malformed `recordIds` or `currentTime`).
'401':
description: Unauthorized — valid bearer token required.
'403':
description: |
Forbidden — the caller's token does not include the
`conversation:chat` OAuth scope.
'500':
description: |
Internal error before the SSE stream is established (for
example, the initial conversation row could not be persisted).
Once the stream is open, terminal failures are surfaced as an
`error` SSE event instead of an HTTP status change.
/conversations:
get:
tags:
- Conversations
summary: List all conversations
description: |
Retrieve paginated conversations for the authenticated user.
**Overview:**
Use the optional `source` query parameter to choose which list to return:
`owned` — only conversations you own (`userId` matches the current user).
`shared` — conversations where you have recipient access
(`isShared` and your user appears in `sharedWith`), without the owner-only branch.
Defaults to `owned` when omitted. Each call returns one list; call twice if you need both.
**Filtering:**
- Only non-archived conversations are returned by default
- Use `/conversations/show/archives` for archived conversations
**Sorting:**
Conversations are sorted by last activity timestamp (most recent first) by default.
operationId: getAllConversations
security:
- bearerAuth: []
- oauth2:
- conversation:read
parameters:
- name: source
in: query
required: false
description: |
`owned` — owner list (`userId` filter only).
`shared` — explicit share grant list (`isShared` + `sharedWith`).
Defaults to `owned` when omitted.
schema:
type: string
enum:
- owned
- shared
default: owned
- name: page
in: query
required: false
description: Page number (1-based). Defaults to 1.
schema:
type: integer
minimum: 1
- name: limit
in: query
required: false
description: Page size. Defaults to 20; capped by the server (max 100).
schema:
type: integer
minimum: 1
- name: sortBy
in: query
required: false
description: Sort field. Invalid values fall back to `lastActivityAt`.
schema:
type: string
enum:
- createdAt
- lastActivityAt
- title
- name: sortOrder
in: query
required: false
description: Sort direction. Defaults to `desc` unless set to `asc`.
schema:
type: string
enum:
- asc
- desc
- name: conversationId
in: query
required: false
description: When set, restricts results to that conversation ID (if visible under the chosen `source`).
schema:
type: string
- name: search
in: query
required: false
description: Case-insensitive match on title and message content (max 1000 characters).
schema:
type: string
- name: startDate
in: query
required: false
description: Filter by `createdAt` ≥ this ISO date.
schema:
type: string
format: date-time
- name: endDate
in: query
required: false
description: Filter by `createdAt` ≤ this ISO date.
schema:
type: string
format: date-time
- name: shared
in: query
required: false
description: |
When set, filters by `isShared`. Accepts case-insensitive
`true`/`false`, or `1`/`0`.
schema:
type: string
responses:
'200':
description: List of conversations for the requested source
content:
application/json:
schema:
type: object
required:
- conversations
- source
- pagination
- filters
- meta
properties:
conversations:
type: array
items:
$ref: '#/components/schemas/ConversationListItem'
source:
type: string
enum:
- owned
- shared
description: Echoes the requested `source` query value.
pagination:
type: object
properties:
page:
type: integer
limit:
type: integer
totalCount:
type: integer
totalPages:
type: integer
hasNextPage:
type: boolean
hasPrevPage:
type: boolean
filters:
type: object
additionalProperties: false
description: |
Filter introspection block. `applied` summarises the
filters active on this request; `available` catalogues
every supported filter with its current value and whether
it is applied.
required:
- applied
- available
properties:
applied:
type: object
additionalProperties: false
required:
- filters
- values
properties:
filters:
type: array
description: Names of filters currently applied.
items:
type: string
values:
type: object
additionalProperties: false
description: |
Current value for each applied filter. Only keys
present in `filters` are populated; others are
omitted.
properties:
search:
type: string
shared:
type: string
tags:
type: string
minMessages:
type: string
sortBy:
type: string
sortOrder:
type: string
startDate:
type: string
endDate:
type: string
messageType:
type: string
page:
type: integer
limit:
type: integer
dateRange:
type: object
additionalProperties: false
properties:
start:
type: string
nullable: true
end:
type: string
nullable: true
available:
type: object
additionalProperties: false
required:
- shared
- tags
- minMessages
- search
- pagination
- sorting
- dateFilters
- messageFilters
- sortingMessages
properties:
shared:
type: object
additionalProperties: false
properties:
values:
type: array
items:
type: string
description: Accepted values for the `shared` query param.
description:
type: string
current:
type: string
nullable: true
applied:
type: boolean
tags:
type: object
additionalProperties: false
properties:
type:
type: string
description:
type: string
current:
type: string
nullable: true
applied:
type: boolean
minMessages:
type: object
additionalProperties: false
properties:
type:
type: string
description:
type: string
current:
type: number
nullable: true
applied:
type: boolean
search:
type: object
additionalProperties: false
properties:
type:
type: string
description:
type: string
current:
type: string
nullable: true
applied:
type: boolean
pagination:
type: object
additionalProperties: false
properties:
page:
type: object
additionalProperties: false
properties:
type:
type: string
current:
type: integer
min:
type: integer
max:
type: integer
default:
type: integer
description:
type: string
applied:
type: boolean
limit:
type: object
additionalProperties: false
properties:
type:
type: string
current:
type: integer
min:
type: integer
max:
type: integer
default:
type: integer
description:
type: string
applied:
type: boolean
sorting:
type: object
additionalProperties: false
properties:
sortBy:
type: object
additionalProperties: false
properties:
values:
type: array
items:
type: string
default:
type: string
description:
type: string
current:
type: string
applied:
type: boolean
sortOrder:
type: object
additionalProperties: false
properties:
values:
type: array
items:
type: string
default:
type: string
description:
type: string
current:
type: string
applied:
type: boolean
dateFilters:
type: object
additionalProperties: false
properties:
dateRange:
type: object
additionalProperties: false
properties:
type:
type: string
description:
type: string
format:
type: string
current:
type: object
additionalProperties: false
properties:
start:
type: string
nullable: true
end:
type: string
nullable: true
applied:
type: boolean
messageFilters:
type: object
additionalProperties: false
properties:
messageType:
type: object
additionalProperties: false
properties:
values:
type: array
items:
type: string
description:
type: string
current:
type: string
nullable: true
applied:
type: boolean
sortingMessages:
type: object
additionalProperties: false
properties:
sortBy:
type: object
additionalProperties: false
properties:
values:
type: array
items:
type: string
default:
type: string
description:
type: string
current:
type: string
sortOrder:
type: object
additionalProperties: false
properties:
values:
type: array
items:
type: string
default:
type: string
description:
type: string
current:
type: string
meta:
type: object
properties:
requestId:
type: string
timestamp:
type: string
format: date-time
duration:
type: integer
'400':
description: |
Bad request — for example, missing or invalid `source` (must be `owned` or `shared`),
invalid date query params, invalid `search` shape, or search text over the length limit.
'401':
description: Unauthorized - Valid bearer token required
/conversations/show/archives:
get:
tags:
- Conversations
summary: List archived conversations
description: |
Retrieve all archived conversations for the authenticated user.
**Overview:**
Archived conversations are hidden from the main list but preserved for reference.
This endpoint returns only conversations where `isArchived: true` and `archivedBy`
is set. Results include conversations the caller owns and those shared with them.
**Filtering and sorting:**
Results can be narrowed using `search`, `shared`, `startDate`, `endDate`, and
`conversationId`. Sorting is controlled by `sortBy` and `sortOrder`. Pagination
is controlled by `page` and `limit`.
**Unarchiving:**
Use `PATCH /conversations/{conversationId}/unarchive` to restore a conversation
to the active list.
operationId: getArchivedConversations
security:
- bearerAuth: []
- oauth2:
- conversation:read
parameters:
- name: page
in: query
required: false
description: Page number (1-indexed)
schema:
type: integer
minimum: 1
maximum: 1000
default: 1
- name: limit
in: query
required: false
description: Items per page
schema:
type: integer
minimum: 1
maximum: 100
default: 20
- name: sortBy
in: query
required: false
description: Field to sort by
schema:
type: string
enum:
- createdAt
- lastActivityAt
- title
default: lastActivityAt
- name: sortOrder
in: query
required: false
description: Sort direction
schema:
type: string
enum:
- asc
- desc
default: desc
- name: search
in: query
required: false
description: Case-insensitive substring match against title and message content (max 1000 chars)
schema:
type: string
maxLength: 1000
- name: shared
in: query
required: false
description: Filter by shared status
schema:
type: boolean
- name: startDate
in: query
required: false
description: Include conversations created on or after this timestamp
schema:
type: string
format: date-time
- name: endDate
in: query
required: false
description: Include conversations created on or before this timestamp
schema:
type: string
format: date-time
- name: conversationId
in: query
required: false
description: Restrict results to a single conversation by identifier
schema:
type: string
format: objectId
responses:
'200':
description: List of archived conversations
content:
application/json:
schema:
type: object
additionalProperties: false
properties:
conversations:
type: array
description: Archived conversations matching the filter
items:
allOf:
- $ref: '#/components/schemas/Conversation'
- type: object
properties:
archivedAt:
type: string
format: date-time
description: Timestamp when the conversation was archived
pagination:
type: object
additionalProperties: false
properties:
page:
type: integer
description: Current page number
limit:
type: integer
description: Items per page
totalCount:
type: integer
description: Total archived conversations matching the filter
totalPages:
type: integer
description: Total pages at the current limit
hasNextPage:
type: boolean
description: Whether a next page exists
hasPrevPage:
type: boolean
description: Whether a previous page exists
filters:
type: object
additionalProperties: false
description: Filters applied to this request and filters available for clients to use
properties:
applied:
type: object
additionalProperties: false
properties:
filters:
type: array
description: Names of filters that were applied
items:
type: string
values:
type: object
additionalProperties: true
description: Map of applied filter name to its current value
available:
type: object
additionalProperties: false
description: Describes filters supported by this endpoint and their current values
properties:
shared:
type: object
additionalProperties: false
properties:
values:
type: array
items:
type: string
description: Allowed values for the `shared` filter
description:
type: string
current:
type: string
nullable: true
description: Current value supplied by the caller, or null
applied:
type: boolean
description: Whether this filter was applied on the request
tags:
type: object
additionalProperties: false
properties:
type:
type: string
description: Expected value type
description:
type: string
current:
type: string
nullable: true
applied:
type: boolean
minMessages:
type: object
additionalProperties: false
properties:
type:
type: string
description:
type: string
current:
type: integer
nullable: true
applied:
type: boolean
search:
type: object
additionalProperties: false
properties:
type:
type: string
description:
type: string
current:
type: string
nullable: true
applied:
type: boolean
pagination:
type: object
additionalProperties: false
properties:
page:
type: object
additionalProperties: false
properties:
type:
type: string
current:
type: integer
min:
type: integer
max:
type: integer
default:
type: integer
description:
type: string
applied:
type: boolean
limit:
type: object
additionalProperties: false
properties:
type:
type: string
current:
type: integer
min:
type: integer
max:
type: integer
default:
type: integer
description:
type: string
applied:
type: boolean
sorting:
type: object
additionalProperties: false
properties:
sortBy:
type: object
additionalProperties: false
properties:
values:
type: array
items:
type: string
default:
type: string
description:
type: string
current:
type: string
applied:
type: boolean
sortOrder:
type: object
additionalProperties: false
properties:
values:
type: array
items:
type: string
enum:
- asc
- desc
default:
type: string
enum:
- asc
- desc
description:
type: string
current:
type: string
enum:
- asc
- desc
applied:
type: boolean
dateFilters:
type: object
additionalProperties: false
properties:
dateRange:
type: object
additionalProperties: false
properties:
type:
type: string
description:
type: string
format:
type: string
description: Expected date format for `startDate` and `endDate` inputs
current:
type: object
additionalProperties: false
properties:
start:
type: string
format: date-time
nullable: true
end:
type: string
format: date-time
nullable: true
applied:
type: boolean
messageFilters:
type: object
additionalProperties: false
properties:
messageType:
type: object
additionalProperties: false
properties:
values:
type: array
items:
type: string
description:
type: string
current:
type: string
nullable: true
applied:
type: boolean
sortingMessages:
type: object
additionalProperties: false
properties:
sortBy:
type: object
additionalProperties: false
properties:
values:
type: array
items:
type: string
default:
type: string
description:
type: string
current:
type: string
sortOrder:
type: object
additionalProperties: false
properties:
values:
type: array
items:
type: string
enum:
- asc
- desc
default:
type: string
enum:
- asc
- desc
description:
type: string
current:
type: string
enum:
- asc
- desc
summary:
type: object
additionalProperties: false
properties:
totalArchived:
type: integer
description: Total archived conversations matching the filter
oldestArchive:
type: string
format: date-time
description: Archive timestamp of the first item in the current page
newestArchive:
type: string
format: date-time
description: Archive timestamp of the last item in the current page
meta:
type: object
additionalProperties: false
properties:
requestId:
type: string
description: Request correlation identifier
timestamp:
type: string
format: date-time
description: Response generation timestamp
duration:
type: integer
description: Server processing time in milliseconds
'401':
description: Unauthorized
/conversations/show/archives/search:
get:
tags:
- Conversations
summary: Search archived conversations
description: |
Search across all archived conversations (assistant and agent) for the authenticated user.
**Overview:**
Performs a case-insensitive substring match against conversation titles and message content
across both assistant (`Conversation`) and agent (`AgentConversation`) archived collections.
Results are merged server-side and sorted by `lastActivityAt` descending.
**Search parameter:**
The `search` query parameter is required, must be a non-empty string, and is capped at
1000 characters. Requests that omit it or exceed the cap return `400`.
**Pagination:**
Results are paginated using `page` and `limit`. The response includes a `pagination`
block with total counts and a `summary` block that breaks matches down by source.
**Item shape:**
Each item is a conversation list entry (no `messages` payload — that field is omitted
for performance) tagged with `source`, plus computed `isOwner`, `accessLevel`,
`archivedAt`, and `archivedBy`. `agentKey` is present only when `source` is `agent`.
operationId: searchArchivedConversations
security:
- bearerAuth: []
- oauth2:
- conversation:read
parameters:
- name: search
in: query
required: true
description: Search term to match against conversation titles and message content (max 1000 chars)
schema:
type: string
minLength: 1
maxLength: 1000
- name: page
in: query
required: false
description: Page number (1-indexed)
schema:
type: integer
minimum: 1
maximum: 1000
default: 1
- name: limit
in: query
required: false
description: Items per page
schema:
type: integer
minimum: 1
maximum: 100
default: 20
responses:
'200':
description: Search results across archived conversations
content:
application/json:
schema:
type: object
additionalProperties: false
properties:
conversations:
type: array
description: Archived conversations (assistant and agent) matching the search term
items:
allOf:
- $ref: '#/components/schemas/ConversationListItem'
- type: object
properties:
source:
type: string
enum:
- assistant
- agent
description: Origin collection of the conversation
agentKey:
type: string
description: Agent identifier — present only when `source` is `agent`
archivedAt:
type: string
format: date-time
description: Timestamp when the conversation was archived
pagination:
type: object
additionalProperties: false
properties:
page:
type: integer
description: Current page number
limit:
type: integer
description: Items per page
totalCount:
type: integer
description: Total matches across assistant and agent archives
totalPages:
type: integer
description: Total pages at the current limit
hasNextPage:
type: boolean
description: Whether a next page exists
hasPrevPage:
type: boolean
description: Whether a previous page exists
summary:
type: object
additionalProperties: false
properties:
totalMatches:
type: integer
description: Combined match count across both collections
assistantMatches:
type: integer
description: Match count in the assistant (`Conversation`) collection
agentMatches:
type: integer
description: Match count in the agent (`AgentConversation`) collection
searchQuery:
type: string
description: Trimmed search term that was applied
meta:
type: object
additionalProperties: false
properties:
requestId:
type: string
description: Request correlation identifier
timestamp:
type: string
format: date-time
description: Response generation timestamp
duration:
type: integer
description: Server processing time in milliseconds
'400':
description: Search parameter missing, empty, not a string, or longer than 1000 characters
'401':
description: Unauthorized
/conversations/{conversationId}:
get:
tags:
- Conversations
summary: Get conversation by ID
description: |
Retrieve a specific conversation with its full message history.
**Overview:**
Returns the complete conversation including all messages, citations,
feedback, and metadata. Messages can be paginated for long conversations.
**Message Pagination:**
For conversations with many messages, use pagination parameters:
- `page`: Page number (default: 1)
- `limit`: Messages per page (default: 10)
- `sortBy`: Sort field (default: createdAt)
- `sortOrder`: 'asc' or 'desc' (default: desc)
**Access Control:**
Users can access conversations they own or that have been shared with them.
operationId: getConversationById
security:
- bearerAuth: []
- oauth2:
- conversation:read
parameters:
- name: conversationId
in: path
required: true
description: Unique conversation identifier
schema:
type: string
format: objectId
example: 507f1f77bcf86cd799439011
- name: page
in: query
description: Page number for message pagination
schema:
type: integer
minimum: 1
default: 1
- name: limit
in: query
description: Number of messages per page
schema:
type: integer
minimum: 1
maximum: 100
default: 20
- name: sortBy
in: query
description: Field to sort messages by
schema:
type: string
enum:
- createdAt
- messageType
- content
default: createdAt
- name: sortOrder
in: query
description: Sort direction
schema:
type: string
enum:
- asc
- desc
default: desc
- name: search
in: query
description: Case-insensitive search across conversation title and message content
schema:
type: string
maxLength: 1000
- name: startDate
in: query
description: Filter messages created on or after this date (ISO 8601)
schema:
type: string
format: date-time
- name: endDate
in: query
description: Filter messages created on or before this date (ISO 8601)
schema:
type: string
format: date-time
- name: shared
in: query
description: Filter by shared status of the conversation
schema:
type: boolean
- name: messageType
in: query
description: Filter messages by type
schema:
type: string
enum:
- user_query
- bot_response
- error
- feedback
- system
responses:
'200':
description: Conversation with paginated messages, applied filter metadata, and request metadata
content:
application/json:
schema:
type: object
additionalProperties: false
properties:
conversation:
type: object
additionalProperties: false
properties:
id:
type: string
format: objectId
description: Unique conversation identifier
title:
type: string
description: Conversation title
initiator:
type: string
format: objectId
description: User who started the conversation
createdAt:
type: string
format: date-time
isShared:
type: boolean
sharedWith:
type: array
items:
type: object
additionalProperties: false
properties:
userId:
type: string
format: objectId
accessLevel:
type: string
enum:
- read
- write
status:
type: string
enum:
- None
- Inprogress
- Complete
- Failed
failReason:
type: string
description: Populated only when `status` is `Failed`
messages:
type: array
description: Page of messages, sliced by `pagination` and ordered by `sortingMessages`
items:
type: object
additionalProperties: false
properties:
_id:
type: string
format: objectId
messageType:
type: string
enum:
- user_query
- bot_response
- error
- feedback
- system
content:
type: string
contentFormat:
type: string
enum:
- MARKDOWN
- JSON
- HTML
confidence:
type: string
enum:
- Very High
- High
- Medium
- Low
- Unknown
nullable: true
description: |
AI confidence in the answer. Present only on `bot_response` messages, and only when the model emitted a trailing confidence block.
This field is now optional and nullable; it was previously always present and non-nullable. Treat a missing or `null` value as "no confidence reported" and guard before using it. Change effective in SDK v1.2.0 (v1.1.0 and earlier always populated it).
citations:
type: array
description: Citations attached to this message. `citationData` is the populated citation document.
items:
type: object
additionalProperties: false
properties:
citationId:
type: string
format: objectId
citationData:
$ref: '#/components/schemas/Citation'
followUpQuestions:
type: array
items:
$ref: '#/components/schemas/FollowUpQuestion'
feedback:
type: array
items:
$ref: '#/components/schemas/MessageFeedback'
referenceData:
type: array
description: Reference IDs surfaced from tool responses, used for follow-up queries
items:
type: object
additionalProperties: false
properties:
name:
type: string
description: Display name shown to the user.
id:
type: string
description: Technical identifier (numeric ID, UUID, etc.).
type:
type: string
description: Item type (e.g. `project`, `issue`, `file`, `notebook`, `page`).
app:
type: string
description: |
Source application (e.g. `jira`, `confluence`,
`sharepoint`, `slack`, `drive`, `gmail`).
webUrl:
type: string
description: URL to open the item in a browser.
metadata:
type: object
additionalProperties:
type: string
description: |
App-specific fields keyed by name (e.g. `key` for a Jira
project, `siteId` for a SharePoint document).
modelInfo:
$ref: '#/components/schemas/ConversationModelInfo'
appliedFilters:
type: object
additionalProperties: false
properties:
apps:
type: array
items:
$ref: '#/components/schemas/AppliedFilterNode'
kb:
type: array
items:
$ref: '#/components/schemas/AppliedFilterNode'
attachments:
type: array
description: |
Files uploaded for this message turn (see
`POST /conversations/attachments/upload`).
items:
$ref: '#/components/schemas/ChatAttachmentRef'
metadata:
type: object
additionalProperties: false
properties:
processingTimeMs:
type: number
modelVersion:
type: string
aiTransactionId:
type: string
createdAt:
type: string
format: date-time
updatedAt:
type: string
format: date-time
modelInfo:
$ref: '#/components/schemas/ConversationModelInfo'
pagination:
type: object
additionalProperties: false
description: |
Pagination over the conversation's messages. Messages are paginated backwards
(newest first), so `messageRange.start`/`messageRange.end` refer to 1-based
positions within the full message list.
properties:
page:
type: integer
limit:
type: integer
totalCount:
type: integer
description: Total number of messages in the conversation
totalPages:
type: integer
hasNextPage:
type: boolean
description: True if there are older messages available
hasPrevPage:
type: boolean
description: True if there are newer messages available
messageRange:
type: object
additionalProperties: false
properties:
start:
type: integer
end:
type: integer
access:
type: object
additionalProperties: false
properties:
isOwner:
type: boolean
accessLevel:
type: string
enum:
- read
- write
filters:
type: object
additionalProperties: false
description: Summary of which filter/sort/pagination parameters were applied to this request, plus the catalog of options available on this endpoint.
properties:
applied:
type: object
additionalProperties: false
properties:
filters:
type: array
description: Names of the filters/parameters that were actually applied
items:
type: string
values:
type: object
additionalProperties: true
description: Map of applied filter name to the value that was applied
available:
type: object
additionalProperties: false
properties:
shared:
type: object
additionalProperties: false
properties:
values:
type: array
items:
type: string
description:
type: string
current:
type: string
nullable: true
applied:
type: boolean
tags:
type: object
additionalProperties: false
description: Advertised in the `available` catalog but not currently applied as a filter by the server.
properties:
type:
type: string
description:
type: string
current:
type: string
nullable: true
applied:
type: boolean
minMessages:
type: object
additionalProperties: false
description: Advertised in the `available` catalog but not currently applied as a filter by the server.
properties:
type:
type: string
description:
type: string
current:
type: string
nullable: true
applied:
type: boolean
search:
type: object
additionalProperties: false
properties:
type:
type: string
description:
type: string
current:
type: string
nullable: true
applied:
type: boolean
pagination:
type: object
additionalProperties: false
properties:
page:
type: object
additionalProperties: false
properties:
type:
type: string
current:
type: integer
min:
type: integer
max:
type: integer
default:
type: integer
description:
type: string
applied:
type: boolean
limit:
type: object
additionalProperties: false
properties:
type:
type: string
current:
type: integer
min:
type: integer
max:
type: integer
default:
type: integer
description:
type: string
applied:
type: boolean
sorting:
type: object
additionalProperties: false
description: Sort applied to the conversation list. Field set echoes back the original list-endpoint sort options even though this endpoint returns a single conversation.
properties:
sortBy:
type: object
additionalProperties: false
properties:
values:
type: array
items:
type: string
default:
type: string
description:
type: string
current:
type: string
applied:
type: boolean
sortOrder:
type: object
additionalProperties: false
properties:
values:
type: array
items:
type: string
default:
type: string
description:
type: string
current:
type: string
applied:
type: boolean
dateFilters:
type: object
additionalProperties: false
properties:
dateRange:
type: object
additionalProperties: false
properties:
type:
type: string
description:
type: string
format:
type: string
current:
type: object
additionalProperties: false
properties:
start:
type: string
nullable: true
end:
type: string
nullable: true
applied:
type: boolean
messageFilters:
type: object
additionalProperties: false
properties:
messageType:
type: object
additionalProperties: false
properties:
values:
type: array
items:
type: string
description:
type: string
current:
type: string
nullable: true
applied:
type: boolean
sortingMessages:
type: object
additionalProperties: false
description: Sort applied to messages within the conversation (separate from the conversation-list `sorting` block).
properties:
sortBy:
type: object
additionalProperties: false
properties:
values:
type: array
items:
type: string
default:
type: string
description:
type: string
current:
type: string
sortOrder:
type: object
additionalProperties: false
properties:
values:
type: array
items:
type: string
default:
type: string
description:
type: string
current:
type: string
meta:
type: object
additionalProperties: false
properties:
requestId:
type: string
timestamp:
type: string
format: date-time
duration:
type: integer
description: Server processing time in milliseconds
conversationId:
type: string
format: objectId
messageCount:
type: integer
description: Total number of messages in the conversation
'401':
description: Unauthorized
'403':
description: Forbidden - No access to this conversation
'404':
description: Conversation not found
delete:
tags:
- Conversations
summary: Delete conversation
description: |
Delete a conversation by its ID.
**Overview:**
Performs a soft delete by setting `isDeleted: true`. The conversation is
removed from listings but preserved in the database. All citations
referenced by messages in the conversation are also soft-deleted.
**Permissions:**
The conversation initiator can always delete. Users the conversation has
been shared with may delete it only when their `sharedWith.accessLevel`
is `write`.
operationId: deleteConversationById
security:
- bearerAuth: []
- oauth2:
- conversation:write
parameters:
- name: conversationId
in: path
required: true
description: Unique conversation identifier
schema:
type: string
format: objectId
responses:
'200':
description: Conversation deleted successfully
content:
application/json:
schema:
type: object
additionalProperties: false
properties:
id:
type: string
format: objectId
description: Identifier of the conversation that was deleted
status:
type: string
enum:
- deleted
description: Outcome of the operation
deletedAt:
type: string
format: date-time
description: Timestamp when the conversation was marked deleted
deletedBy:
type: string
format: objectId
description: Identifier of the user who performed the delete
citationsDeleted:
type: integer
description: Number of citations soft-deleted alongside the conversation
meta:
type: object
additionalProperties: false
properties:
requestId:
type: string
description: Server-assigned identifier for the request
timestamp:
type: string
format: date-time
description: Server time the response was produced
duration:
type: integer
description: Server processing time in milliseconds
'400':
description: Invalid `conversationId` path parameter
'401':
description: Unauthorized
'403':
description: Forbidden - token is missing the `conversation:write` scope
'404':
description: Conversation not found, already deleted, or caller has no delete access
'500':
description: Internal server error while deleting the conversation
/conversations/{conversationId}/messages/stream:
post:
tags:
- Conversations
summary: Add message to a conversation with streaming response
description: |
Add a follow-up message to an existing conversation and stream the
assistant's response over Server-Sent Events.
Functionally equivalent to `POST /conversations/{conversationId}/messages`
but the response is delivered as an SSE stream so clients can render
the answer incrementally.
The wire vocabulary is described by `AssistantMessageStreamSSEEvent`.
It is the same event set as `/conversations/stream`; only the
`connected` and `complete` payloads differ because the conversation
already exists when this route is called.
operationId: addMessageStream
security:
- bearerAuth: []
- oauth2:
- conversation:chat
parameters:
- name: conversationId
in: path
required: true
description: |
Identifier of the conversation to append the message to. The
conversation must belong to the caller and must not be deleted.
schema:
type: string
format: objectId
requestBody:
required: true
description: Request payload
content:
application/json:
schema:
$ref: '#/components/schemas/AddMessageRequest'
responses:
'200':
description: |
SSE stream established. The body is a sequence of
`text/event-stream` frames using the event vocabulary described
on the schema below.
content:
text/event-stream:
schema:
$ref: '#/components/schemas/AssistantMessageStreamSSEEvent'
'400':
description: |
Invalid request — `query` is missing or empty, or another field
fails validation (for example a malformed `currentTime`).
'401':
description: Unauthorized — valid bearer token required.
'403':
description: |
Forbidden — the caller's token does not include the
`conversation:chat` OAuth scope.
'404':
description: |
The conversation does not exist, is deleted, or does not belong
to the caller.
'500':
description: |
Internal error before the SSE stream is established (for
example, the user message could not be persisted to the
conversation). Once the stream is open, terminal failures are
surfaced as an `error` SSE event instead of an HTTP status
change.
/conversations/{conversationId}/title:
patch:
tags:
- Conversations
summary: Update conversation title
description: |
Update the title of a conversation.
**Overview:**
Conversation titles are auto-generated from the first query by default.
Use this endpoint to set a custom, more descriptive title.
**Title limits:**
- Minimum: 1 character
- Maximum: 200 characters
**Permissions:**
The conversation must exist, belong to the calling user's organization,
be owned by the caller (matched on `userId`), and not be soft-deleted.
operationId: updateConversationTitle
security:
- bearerAuth: []
- oauth2:
- conversation:write
parameters:
- name: conversationId
in: path
required: true
description: Unique conversation identifier
schema:
type: string
format: objectId
requestBody:
required: true
description: Request payload
content:
application/json:
schema:
type: object
additionalProperties: false
required:
- title
properties:
title:
type: string
minLength: 1
maxLength: 200
description: New conversation title
example: Q4 Sales Analysis Discussion
responses:
'200':
description: Title updated successfully
content:
application/json:
schema:
type: object
additionalProperties: false
required:
- conversation
- meta
properties:
conversation:
type: object
additionalProperties: false
description: |
The full conversation document after the title update,
returned as stored in MongoDB.
required:
- _id
- userId
- orgId
- initiator
- messages
- isShared
- isDeleted
- isArchived
- sharedWith
- conversationErrors
- lastActivityAt
- createdAt
- updatedAt
- __v
properties:
_id:
type: string
format: objectId
description: Unique conversation identifier
userId:
type: string
format: objectId
description: ID of the user who owns this conversation
orgId:
type: string
format: objectId
description: Organization this conversation belongs to
title:
type: string
description: |
Conversation title. Present and equal to the value
submitted in the request body after a successful
update.
initiator:
type: string
format: objectId
description: User who started the conversation
messages:
type: array
description: All messages stored on this conversation.
items:
type: object
additionalProperties: false
required:
- _id
- messageType
- content
- contentFormat
- citations
- followUpQuestions
- feedback
- referenceData
- createdAt
- updatedAt
properties:
_id:
type: string
format: objectId
messageType:
type: string
enum:
- user_query
- bot_response
- error
- feedback
- system
content:
type: string
contentFormat:
type: string
enum:
- MARKDOWN
- JSON
- HTML
default: MARKDOWN
confidence:
type: string
nullable: true
description: |
AI confidence in the answer. Present only on
`bot_response` messages, and only when the
model emitted a trailing confidence block.
This field is now optional and nullable; it was previously always present and non-nullable. Treat a missing or `null` value as "no confidence reported" and guard before using it. Change effective in SDK v1.3.0 (v1.2.0 and earlier always populated it).
citations:
type: array
description: |
References to source documents used in the
response, stored as raw citation pointers
(not populated on this endpoint).
items:
$ref: '#/components/schemas/CitationReference'
followUpQuestions:
type: array
items:
$ref: '#/components/schemas/FollowUpQuestion'
feedback:
type: array
items:
$ref: '#/components/schemas/MessageFeedback'
referenceData:
type: array
description: |
Reference IDs surfaced from tool responses,
used for follow-up queries.
items:
type: object
additionalProperties: false
properties:
name:
type: string
description: Display name shown to the user.
id:
type: string
description: Technical identifier (numeric ID, UUID, etc.).
type:
type: string
description: Item type (e.g. `project`, `issue`, `file`, `notebook`, `page`).
app:
type: string
description: |
Source application (e.g. `jira`, `confluence`,
`sharepoint`, `slack`, `drive`, `gmail`).
webUrl:
type: string
description: URL to open the item in a browser.
metadata:
type: object
additionalProperties:
type: string
description: |
App-specific fields keyed by name (e.g. `key` for a Jira
project, `siteId` for a SharePoint document).
modelInfo:
$ref: '#/components/schemas/ConversationModelInfo'
appliedFilters:
type: object
additionalProperties: false
properties:
apps:
type: array
items:
$ref: '#/components/schemas/AppliedFilterNode'
kb:
type: array
items:
$ref: '#/components/schemas/AppliedFilterNode'
attachments:
type: array
description: |
Files uploaded for this message turn (see
`POST /conversations/attachments/upload`).
items:
$ref: '#/components/schemas/ChatAttachmentRef'
metadata:
type: object
additionalProperties: false
properties:
processingTimeMs:
type: number
modelVersion:
type: string
aiTransactionId:
type: string
reason:
type: string
createdAt:
type: string
format: date-time
updatedAt:
type: string
format: date-time
status:
type: string
enum:
- None
- Inprogress
- Complete
- Failed
description: |
Current status of the conversation:
- `None` — no activity yet
- `Inprogress` — AI is processing
- `Complete` — response ready
- `Failed` — error occurred
failReason:
type: string
description: |
Error description, populated only when `status`
is `Failed`.
modelInfo:
$ref: '#/components/schemas/ConversationModelInfo'
isShared:
type: boolean
default: false
description: Whether this conversation is shared with others
shareLink:
type: string
description: Shareable link if the conversation is shared
sharedWith:
type: array
description: Users this conversation is shared with
items:
type: object
additionalProperties: false
required:
- userId
- accessLevel
properties:
userId:
type: string
format: objectId
accessLevel:
type: string
enum:
- read
- write
default: read
isArchived:
type: boolean
default: false
description: Whether this conversation is archived
archivedBy:
type: string
format: objectId
nullable: true
description: |
User ID of the last user who archived this row, or `null` after
unarchive cleared the archive state. Absent on rows that have
never been archived.
isDeleted:
type: boolean
default: false
description: Whether this conversation has been soft-deleted.
deletedBy:
type: string
format: objectId
description: User who soft-deleted this conversation.
conversationErrors:
type: array
description: |
Errors recorded against this conversation
(e.g. failed message generations).
items:
type: object
additionalProperties: false
required:
- _id
- message
- timestamp
properties:
_id:
type: string
format: objectId
description: Sub-document identifier auto-assigned by MongoDB.
message:
type: string
errorType:
type: string
timestamp:
type: string
format: date-time
description: |
Time the error was recorded. Server-defaulted
to `Date.now` when the entry is pushed, so
always present.
messageId:
type: string
format: objectId
stack:
type: string
metadata:
type: object
additionalProperties: true
description: |
Free-form metadata attached to this error
entry (Map of Mixed in the schema).
metadata:
type: object
additionalProperties: true
description: Free-form metadata attached to the conversation.
lastActivityAt:
type: integer
format: int64
description: |
Unix timestamp of the last activity, stored as
epoch milliseconds (server-side default `Date.now`).
createdAt:
type: string
format: date-time
updatedAt:
type: string
format: date-time
__v:
type: integer
description: Mongoose document version key.
meta:
type: object
additionalProperties: false
required:
- requestId
- timestamp
- duration
properties:
requestId:
type: string
description: |
Server-side request identifier. Read from the
`X-Request-ID` header when supplied, otherwise
auto-generated, so this field is always present.
timestamp:
type: string
format: date-time
duration:
type: integer
description: Server-side processing time in milliseconds.
'400':
description: |
Invalid request. Possible causes:
- `title` missing, empty, or longer than 200 characters.
- `conversationId` path parameter is not a valid ObjectId.
'401':
description: Unauthorized
'403':
description: Forbidden - token is missing the `conversation:write` scope
'404':
description: Conversation not found, soft-deleted, or not owned by the caller.
'500':
description: Persistence layer failed to update the conversation document.
/conversations/{conversationId}/archive:
patch:
tags:
- Conversations
summary: Archive conversation
description: |
Archive a conversation to hide it from the main list.
**Overview:**
Archived conversations are preserved but hidden from the default conversation list.
Use archiving to clean up your workspace without permanently deleting conversations.
**Access:**
The caller must be the conversation's initiator, or be listed in `sharedWith`
with `accessLevel: write`. Already-archived conversations return `400`.
**Retrieval:**
View archived conversations using `GET /conversations/show/archives`.
Restore one with `PATCH /conversations/{conversationId}/unarchive`.
operationId: archiveConversation
security:
- bearerAuth: []
- oauth2:
- conversation:write
parameters:
- name: conversationId
in: path
required: true
description: Conversation identifier
schema:
type: string
format: objectId
responses:
'200':
description: Conversation archived successfully
content:
application/json:
schema:
type: object
additionalProperties: false
properties:
id:
type: string
format: objectId
description: Conversation identifier
status:
type: string
enum:
- archived
description: New archive status of the conversation
archivedBy:
type: string
format: objectId
description: User who archived the conversation
archivedAt:
type: string
format: date-time
description: Timestamp when the conversation was archived
meta:
type: object
additionalProperties: false
properties:
requestId:
type: string
description: Request correlation identifier
timestamp:
type: string
format: date-time
description: Response generation timestamp
duration:
type: integer
description: Server processing time in milliseconds
'400':
description: Conversation is already archived
'401':
description: Unauthorized
'404':
description: Conversation not found or caller lacks archive permission
/conversations/{conversationId}/unarchive:
patch:
tags:
- Conversations
summary: Unarchive conversation
description: |
Restore an archived conversation.
- Path params: `conversationId`
- Query params: none
- Body: none
operationId: unarchiveConversation
security:
- bearerAuth: []
- oauth2:
- conversation:write
parameters:
- name: conversationId
in: path
required: true
description: Conversation identifier
schema:
type: string
format: objectId
responses:
'200':
description: Conversation unarchived successfully
content:
application/json:
schema:
type: object
additionalProperties: false
properties:
id:
type: string
format: objectId
description: Conversation identifier
status:
type: string
enum:
- unarchived
description: New archive status of the conversation
unarchivedBy:
type: string
format: objectId
description: User who unarchived the conversation
unarchivedAt:
type: string
format: date-time
description: Timestamp when the conversation was unarchived
meta:
type: object
additionalProperties: false
properties:
requestId:
type: string
description: Request correlation identifier
timestamp:
type: string
format: date-time
description: Response generation timestamp
duration:
type: integer
description: Server processing time in milliseconds
'400':
description: Conversation is not currently archived
'401':
description: Unauthorized
'403':
description: Forbidden - token is missing the `conversation:write` scope
'404':
description: Conversation not found or caller lacks unarchive permission
'500':
description: Persistence layer failed to update the conversation document.
/conversations/{conversationId}/message/{messageId}/regenerate:
post:
tags:
- Conversations
summary: Regenerate AI response
description: |
Regenerate the AI response for a specific message and stream the new
answer over Server-Sent Events.
**Overview:**
If you're not satisfied with an AI response, use this endpoint to generate
a new answer. The original user query is re-processed and a new bot
response replaces the previous one in place.
**Constraints:**
- Only the *last* message of the conversation can be regenerated.
- The target message must be of type `bot_response`.
**Use Cases:**
- Response was incomplete or unclear
- Want to try a different AI model
- New documents have been indexed since original response
**Model Override:**
Specify `modelKey` to use a different model for regeneration.
**Streaming:**
The response is delivered as an SSE (`text/event-stream`) stream. The
exact event vocabulary depends on `chatMode`:
- For non-agent modes (e.g. `internal_search`, `web_search`) the
request is dispatched to the assistant chat backend.
- For agent modes (e.g. `agent:auto`) the request is dispatched to
the agent backend with a placeholder agent built from the caller's
workspace, which can additionally emit `tool_result` and
`tool_execution_complete` events.
See `SSEEvent` for the full union of event names this endpoint can
emit across both backends.
operationId: regenerateAnswer
security:
- bearerAuth: []
- oauth2:
- conversation:chat
parameters:
- name: conversationId
in: path
required: true
schema:
type: string
format: objectId
- name: messageId
in: path
required: true
description: ID of the message to regenerate response for
schema:
type: string
format: objectId
requestBody:
description: Request payload
content:
application/json:
schema:
$ref: '#/components/schemas/RegenerateRequest'
responses:
'200':
description: |
SSE stream established. The body is a sequence of
`text/event-stream` frames using the event vocabulary described
on `SSEEvent`. The exact subset of events emitted depends on
`chatMode` (see the route description for routing rules).
Lifecycle (all event names are sent verbatim on the wire):
- `connected` — `{ "message": "SSE connection established" }`.
Fired once on connection by the API layer.
- `status` — progress messages from the AI backend. Possible
`status` sub-values include `started`, `transforming`,
`searching`, `processing`, `checking_tools`,
`generating_answer`, `generating`, `analyzing`, `evaluating`,
`planning`, `executing`, `retrying`, `continuing`, `success`,
`skipped`, `pending`, `keepalive`, `cascade_error`, and
backend-defined values that may be added over time.
- `answer_chunk` — incremental token batches with running
`accumulated` text, accumulated `citations`, and the
backend-supplied `confidence` (typically null until the final
chunk).
- `tool_calls` / `tool_call` / `tool_success` / `tool_error` —
emitted when the model invokes tools (agent chat modes, or the
non-agent path when SQL / record-fetch tools are configured).
- `tool_result` / `tool_execution_complete` — additional tool
lifecycle events emitted only on the agent-mode path.
- `restreaming` — emitted when the LLM is restarted with new
context (e.g. before a citation-verification pass or
reflection-driven retry).
- `metadata` — `{}` keep-alive emitted by the JSON-streaming
branch while waiting for the next safe-to-flush chunk.
- `complete` — `{ "conversation": Conversation, "recordsUsed":
number, "meta": { "requestId": string, "timestamp": string,
"duration": number, "recordsUsed": number } }`. Fired once
after the regeneration is persisted; the new bot response
replaces the previous one in `conversation.messages` at the
same index. The AI backend's own `complete` frame is consumed
server-side and is **not** forwarded — clients see only this
server-defined frame.
- `error` — `{ "error": string, "details"?: string }`. Fired if
the stream fails; the previous bot response is replaced with an
error message and the conversation row is marked FAILED before
close.
Clients should ignore unknown event names rather than treating
them as errors.
content:
text/event-stream:
schema:
$ref: '#/components/schemas/SSEEvent'
'400':
description: |
Cannot regenerate. Common causes: target message is not the last
message in the conversation, target message is not of type
`bot_response`, or no preceding `user_query` exists.
'401':
description: Unauthorized
'404':
description: Conversation or message not found
/conversations/{conversationId}/message/{messageId}/feedback:
post:
tags:
- Conversations
summary: Submit feedback on AI response
description: |
Append a feedback entry to a bot-response message.
**Overview**
Feedback helps improve AI response quality over time. You can record an
overall helpfulness signal, issue categories, and free-text comments.
Each call appends a new entry to the message; previous entries are
preserved.
**Feedback options**
- `isHelpful` — overall thumbs up/down.
- `categories` — issue or positive categories from a fixed list.
- `comments` — free-text `positive` and `negative`.
**Restrictions**
Feedback can only be submitted on `bot_response` messages — user
queries and system messages are rejected with `400`.
operationId: updateMessageFeedback
security:
- bearerAuth: []
- oauth2:
- conversation:write
parameters:
- name: conversationId
in: path
required: true
description: Unique conversation identifier.
schema:
type: string
format: objectId
- name: messageId
in: path
required: true
description: Identifier of the bot-response message being rated.
schema:
type: string
format: objectId
requestBody:
required: true
description: Request payload
content:
application/json:
schema:
$ref: '#/components/schemas/MessageFeedbackSubmitRequest'
responses:
'200':
description: Feedback submitted successfully.
content:
application/json:
schema:
$ref: '#/components/schemas/MessageFeedbackUpdateResponse'
'400':
description: |
Invalid request. Possible causes:
- Feedback target is not a `bot_response` message.
- A `categories` value is not in the allowed list.
- `conversationId` or `messageId` is not a valid ObjectId.
'401':
description: Unauthorized.
'404':
description: |
Conversation or message not found, or the caller does not have
access to this conversation.
'500':
description: Persistence layer failed to append the feedback entry.
/search:
post:
tags:
- Semantic Search
summary: Perform semantic search
description: |
Run a semantic search across your organization's knowledge base.
Matching is meaning-based, so relevant results surface even when
the wording differs from the query.
Use optional `filters` to narrow the scope:
- `filters.apps` — restrict to specific connector apps (for
example Google Drive or Confluence).
- `filters.kb` — restrict to specific knowledge bases.
The response returns a `searchId` for the persisted search along
with ranked matches, each carrying a relevance score and the
source document's metadata. Past searches can be retrieved via
`GET /search`.
operationId: search
security:
- bearerAuth: []
- oauth2:
- semantic:write
requestBody:
required: true
description: Request payload
content:
application/json:
schema:
$ref: '#/components/schemas/SemanticSearchRequest'
examples:
simple:
summary: Basic search
value:
query: company vacation policy
limit: 10
responses:
'200':
description: Search ID plus retrieval payload (`searchResponse`) from the AI search service
content:
application/json:
schema:
$ref: '#/components/schemas/SemanticSearchExecuteResponse'
'400':
description: |
Invalid request — `query` is missing, empty, or the request
body fails validation.
'401':
description: |
Missing or invalid bearer token.
'403':
description: |
Bearer token lacks the `semantic:write` scope.
'404':
description: |
A referenced knowledge base or app filter could not be
resolved.
'500':
description: |
Unexpected server error while executing the search, or the
upstream AI search service was unreachable.
'502':
description: |
The upstream AI search service returned an invalid response.
'503':
description: |
The upstream AI search service is temporarily unavailable.
'504':
description: |
The upstream AI search service timed out before returning a
response.
get:
tags:
- Semantic Search
summary: Get search history
description: |
Retrieve the authenticated user's persisted search history.
Returns searches the user owns along with searches shared with them,
scoped to the caller's organization. Archived and deleted entries are
excluded. Citation references on this endpoint are returned as raw
identifier strings; use `GET /search/{searchId}` to fetch a single
search with its citations fully expanded.
Pagination defaults to `page=1, limit=20` (maximum `limit` is 100).
Results are sorted by most recent activity by default.
operationId: searchHistory
security:
- bearerAuth: []
- oauth2:
- semantic:read
parameters:
- name: page
in: query
description: Page number to return. Must be within `[1, 1000]`.
schema:
type: integer
minimum: 1
maximum: 1000
default: 1
- name: limit
in: query
description: Number of items per page. Values are clamped to the range `[1, 100]`.
schema:
type: integer
minimum: 1
maximum: 100
default: 20
- name: sortBy
in: query
description: |
Field used to sort results. Any value other than `createdAt`,
`lastActivityAt`, or `title` is treated as `lastActivityAt`.
schema:
type: string
enum:
- createdAt
- lastActivityAt
- title
default: lastActivityAt
- name: sortOrder
in: query
description: Sort direction applied to `sortBy`.
schema:
type: string
enum:
- asc
- desc
default: desc
- name: search
in: query
description: |
Case-insensitive substring to match against a search's title and
message content. Regex metacharacters are escaped automatically.
Values longer than 1000 characters are rejected with `400`.
schema:
type: string
- name: shared
in: query
description: |
Filter results by their shared status. Accepted values are
`'true'` / `'1'` (return only shared searches) and
`'false'` / `'0'` (exclude shared searches). Matching is
case-insensitive and surrounding whitespace is trimmed.
schema:
type: string
enum:
- 'true'
- 'false'
- '1'
- '0'
- name: startDate
in: query
description: ISO 8601 timestamp used as the lower bound for a search's creation date.
schema:
type: string
format: date-time
- name: endDate
in: query
description: ISO 8601 timestamp used as the upper bound for a search's creation date.
schema:
type: string
format: date-time
responses:
'200':
description: |
Persisted search history plus pagination, applied/available filter
metadata, and a request-scoped `meta` block.
content:
application/json:
schema:
$ref: '#/components/schemas/SemanticSearchHistoryResponse'
'400':
description: |
Invalid request, raised when
a query parameter fails validation — for example a malformed
`startDate` / `endDate`, a `search` value over 1000 characters,
or a query value that trips the XSS guard.
content:
application/json:
schema:
type: object
additionalProperties: false
description: Error envelope for a failed request.
properties:
error:
type: object
additionalProperties: false
description: Error payload.
properties:
code:
type: string
description: |
Machine-readable error code. For this status the
value is either `VALIDATION_ERROR` (request failed
schema validation) or `HTTP_BAD_REQUEST` (semantic
validation failed — malformed date, value over the
allowed length, or XSS-guard trip).
message:
type: string
description: Human-readable description of the failure.
required:
- code
- message
required:
- error
'401':
description: |
Missing or invalid bearer token.
content:
application/json:
schema:
type: object
additionalProperties: false
description: Error envelope for a failed request.
properties:
error:
type: object
additionalProperties: false
description: Error payload.
properties:
code:
type: string
description: |
Machine-readable error code. For this status the
value is `HTTP_UNAUTHORIZED` (missing, invalid, or
expired bearer token, user no longer exists, or the
session has been invalidated).
message:
type: string
description: Human-readable description of the failure.
required:
- code
- message
required:
- error
'403':
description: |
Bearer token lacks the `semantic:read` scope.
content:
application/json:
schema:
type: object
additionalProperties: false
description: Error envelope for a failed request.
properties:
error:
type: object
additionalProperties: false
description: Error payload.
properties:
code:
type: string
description: |
Machine-readable error code. For this status the
value is `HTTP_FORBIDDEN` (the token is valid but
does not carry the `semantic:read` scope).
message:
type: string
description: Human-readable description of the failure.
required:
- code
- message
required:
- error
'500':
description: |
Server error. Possible causes:
- Explicit `InternalServerError`
or any other 500 `BaseError` thrown by the handler.
- Non-`BaseError` exception caught by the
global error middleware.
- Response serializer fallback.
content:
application/json:
schema:
type: object
additionalProperties: false
description: Error envelope for a failed request.
properties:
error:
type: object
additionalProperties: false
description: Error payload.
properties:
code:
type: string
description: |
Machine-readable error code. For this status the
value is `HTTP_INTERNAL_SERVER_ERROR` for an
explicit server-side failure, or `INTERNAL_ERROR`
for an unhandled exception coerced by the global
error middleware.
message:
type: string
description: Human-readable description of the failure.
required:
- code
- message
required:
- error
delete:
tags:
- Semantic Search
summary: Clear all search history
description: |
Permanently delete every persisted search row owned by, or shared
with, the authenticated user, along with the citation rows those
searches reference. The action cannot be undone.
Scoped to the caller's org and limited to rows where
`isDeleted: false` and `isArchived: false`. If nothing matches
(including the case where every row is already archived), the
endpoint returns `404` rather than a successful no-op.
operationId: deleteSearchHistory
security:
- bearerAuth: []
- oauth2:
- semantic:delete
parameters:
- name: search
in: query
description: |
Restrict the deletion to rows whose `title` or `messages.content`
matches this case-insensitive substring. Special regex characters
are escaped before the lookup; values over 1000 chars are
rejected with `400`.
schema:
type: string
- name: shared
in: query
description: |
Restrict the deletion to rows with this `isShared` value
(`'true'` / `'false'`).
schema:
type: string
enum:
- 'true'
- 'false'
- name: startDate
in: query
description: |
ISO 8601 lower bound for `createdAt`. Combined with `endDate`
to scope which rows are deleted.
schema:
type: string
format: date-time
- name: endDate
in: query
description: ISO 8601 upper bound for `createdAt`.
schema:
type: string
format: date-time
responses:
'200':
description: Search history deleted successfully.
content:
application/json:
schema:
type: object
additionalProperties: false
required:
- message
properties:
message:
type: string
'400':
description: |
Invalid request, raised
from the shared filter helper when a query parameter fails
validation — for example a malformed `startDate` / `endDate`,
a `search` value over 1000 characters, or a `search` value
that trips the XSS guard.
'401':
description: |
Missing or invalid bearer token.
'403':
description: |
Bearer token lacks the `semantic:delete` scope.
'404':
description: |
No matching rows. Returned when the caller has no owned or
shared searches that satisfy the filter.
'500':
description: |
Server error. Possible causes:
- Explicit `InternalServerError`
or any other 500 `BaseError` thrown by the handler.
- Non-`BaseError` exception caught by the
global error middleware.
- Response serializer fallback.
/search/{searchId}:
get:
tags:
- Semantic Search
summary: Get search by ID
description: |
Retrieve a previously persisted search by its id, scoped to the
caller's org.
The response body is always an **array** containing zero or one
persisted search document. An unknown id returns an empty array
with a `200` status — callers should check array length rather
than relying on a `404`.
operationId: getSearchById
security:
- bearerAuth: []
- oauth2:
- semantic:read
parameters:
- name: searchId
in: path
required: true
description: Unique search identifier
schema:
type: string
format: objectId
responses:
'200':
description: Array containing zero or one persisted search document.
content:
application/json:
schema:
$ref: '#/components/schemas/PersistedSemanticSearchEnvelope'
'400':
description: |
Invalid request — `searchId`
failed Zod validation (not a valid ObjectId).
content:
application/json:
schema:
type: object
additionalProperties: false
required:
- error
properties:
error:
type: object
additionalProperties: false
required:
- code
- message
properties:
code:
type: string
enum:
- VALIDATION_ERROR
description: |
Machine-readable error code. `VALIDATION_ERROR`
is emitted when the request fails Zod
validation.
message:
type: string
description: Human-readable description of the failure.
'401':
description: |
Missing or invalid bearer token.
content:
application/json:
schema:
type: object
additionalProperties: false
required:
- error
properties:
error:
type: object
additionalProperties: false
required:
- code
- message
properties:
code:
type: string
enum:
- HTTP_UNAUTHORIZED
description: |
Machine-readable error code. `HTTP_UNAUTHORIZED`
is emitted when the bearer token is missing,
invalid, or expired.
message:
type: string
description: Human-readable description of the failure.
'403':
description: |
Bearer token lacks the `semantic:read` scope.
content:
application/json:
schema:
type: object
additionalProperties: false
required:
- error
properties:
error:
type: object
additionalProperties: false
required:
- code
- message
properties:
code:
type: string
enum:
- HTTP_FORBIDDEN
description: |
Machine-readable error code. `HTTP_FORBIDDEN`
is emitted when the bearer token is valid but
lacks the required scope.
message:
type: string
description: Human-readable description of the failure.
'404':
description: |
Reserved for parity with sibling routes; this endpoint
currently returns `200` with an empty array for an unknown
id rather than emitting `404`.
content:
application/json:
schema:
type: object
additionalProperties: false
required:
- error
properties:
error:
type: object
additionalProperties: false
required:
- code
- message
properties:
code:
type: string
enum:
- HTTP_NOT_FOUND
description: |
Machine-readable error code. `HTTP_NOT_FOUND`
is emitted when the addressed resource does
not exist.
message:
type: string
description: Human-readable description of the failure.
'500':
description: |
Server error. Possible causes:
- Explicit `InternalServerError`
or any other 500 `BaseError` thrown by the handler.
- Non-`BaseError` exception caught by the
global error middleware.
- Response serializer fallback.
content:
application/json:
schema:
type: object
additionalProperties: false
required:
- error
properties:
error:
type: object
additionalProperties: false
required:
- code
- message
properties:
code:
type: string
enum:
- HTTP_INTERNAL_SERVER_ERROR
- INTERNAL_ERROR
- MIDDLEWARE_ERROR
description: |
Machine-readable error code.
- `HTTP_INTERNAL_SERVER_ERROR` — explicit
`InternalServerError` raised by the handler.
- `INTERNAL_ERROR` — unhandled exception
caught by the global error middleware.
- `MIDDLEWARE_ERROR` — the error middleware
itself failed while serializing the
response.
message:
type: string
description: Human-readable description of the failure.
delete:
tags:
- Semantic Search
summary: Delete search by ID
description: |
Permanently delete a single persisted search row, plus every
citation row referenced by its `citationIds`. The caller must
either own the row or have it shared with them.
Scoped to the caller's org and limited to rows where
`isDeleted: false` and `isArchived: false`; archived or
already-deleted rows surface as `404`.
operationId: deleteSearchById
security:
- bearerAuth: []
- oauth2:
- semantic:delete
parameters:
- name: searchId
in: path
required: true
description: ObjectId of the persisted search row to delete.
schema:
type: string
format: objectId
- name: search
in: query
description: |
Additional substring filter against `title` / `messages.content`.
The row is only deleted if the `searchId` row also matches this
filter; otherwise `404`. Special regex characters are escaped;
values over 1000 chars or tripping the XSS guard yield `400`.
schema:
type: string
- name: shared
in: query
description: |
Additional `isShared` filter (`'true'` / `'false'`). The row is
only deleted if it also matches this value.
schema:
type: string
enum:
- 'true'
- 'false'
- name: startDate
in: query
description: |
ISO 8601 lower bound for `createdAt`. The row is only deleted
if its `createdAt` is on or after this value.
schema:
type: string
format: date-time
- name: endDate
in: query
description: |
ISO 8601 upper bound for `createdAt`. The row is only deleted
if its `createdAt` is on or before this value.
schema:
type: string
format: date-time
responses:
'200':
description: Search deleted successfully.
content:
application/json:
schema:
type: object
additionalProperties: false
required:
- message
properties:
message:
type: string
'400':
description: |
Invalid request. Possible causes:
- `searchId` failed Zod validation
(not a valid ObjectId).
- A query parameter passed through to
the shared filter helper failed validation, e.g. a
malformed `startDate` / `endDate`, or a `search` value
over 1000 characters or tripping the XSS guard.
'401':
description: |
Missing or invalid bearer token.
'403':
description: |
Bearer token lacks the `semantic:delete` scope.
'404':
description: |
No search matched. Returned when the id does not exist for
this caller, or when the row is archived or already deleted.
'500':
description: |
Server error. Possible causes:
- Explicit `InternalServerError`
or any other 500 `BaseError` thrown by the handler.
- Non-`BaseError` exception caught by the
global error middleware.
- Response serializer fallback.
/search/{searchId}/archive:
patch:
tags:
- Semantic Search
summary: Archive a search
description: |
Archive a specific search result. Archived searches are hidden
from the default search history view but remain retrievable via
the archive-aware listing endpoints.
operationId: archiveSearch
security:
- bearerAuth: []
- oauth2:
- semantic:write
parameters:
- name: searchId
in: path
required: true
description: Unique search identifier
schema:
type: string
format: objectId
responses:
'200':
description: Search archived successfully
content:
application/json:
schema:
type: object
additionalProperties: false
required:
- id
- status
- archivedBy
- archivedAt
- meta
properties:
id:
type: string
format: objectId
description: Unique identifier of the archived search.
example: 65f1c0a4e2b9c4d8f3a1b2c3
status:
type: string
enum:
- archived
description: Resulting status of the search after the operation.
example: archived
archivedBy:
type: string
format: objectId
description: User ID of the user who archived the search.
example: 65f1c0a4e2b9c4d8f3a1b2c4
archivedAt:
type: string
format: date-time
description: Timestamp when the search was archived.
example: '2026-05-10T12:34:56.789Z'
meta:
type: object
additionalProperties: false
required:
- timestamp
- duration
properties:
requestId:
type: string
description: Server-assigned request identifier for tracing. Omitted when not available.
example: req_8f3a1b2c
timestamp:
type: string
format: date-time
description: Server timestamp when the response was produced.
example: '2026-05-10T12:34:56.789Z'
duration:
type: integer
description: Time taken to process the request, in milliseconds.
example: 42
'400':
description: |
Invalid request. Possible causes:
- `searchId` failed Zod validation
(not a valid ObjectId).
- The target search is already archived.
'401':
description: |
Missing or invalid bearer token.
'403':
description: |
Bearer token lacks the `semantic:write` scope.
'404':
description: |
Search not found, or not owned by the caller's org.
'500':
description: |
Persistence layer failed to update the search document.
/search/{searchId}/unarchive:
patch:
tags:
- Semantic Search
summary: Unarchive a search
description: |
Restore a previously archived search result back to the active search history.
operationId: unarchiveSearch
security:
- bearerAuth: []
- oauth2:
- semantic:write
parameters:
- name: searchId
in: path
required: true
description: Unique search identifier
schema:
type: string
format: objectId
responses:
'200':
description: Search unarchived successfully
content:
application/json:
schema:
type: object
additionalProperties: false
required:
- id
- status
- unarchivedBy
- unarchivedAt
- meta
properties:
id:
type: string
format: objectId
description: Unique identifier of the unarchived search.
example: 65f1c0a4e2b9c4d8f3a1b2c3
status:
type: string
enum:
- unarchived
description: Resulting status of the search after the operation.
example: unarchived
unarchivedBy:
type: string
format: objectId
description: User ID of the user who unarchived the search.
example: 65f1c0a4e2b9c4d8f3a1b2c4
unarchivedAt:
type: string
format: date-time
description: Timestamp when the search was unarchived.
example: '2026-05-10T12:34:56.789Z'
meta:
type: object
additionalProperties: false
required:
- timestamp
- duration
properties:
requestId:
type: string
description: Server-assigned request identifier for tracing. Omitted when not available.
example: req_8f3a1b2c
timestamp:
type: string
format: date-time
description: Server timestamp when the response was produced.
example: '2026-05-10T12:34:56.789Z'
duration:
type: integer
description: Time taken to process the request, in milliseconds.
example: 42
'400':
description: |
Invalid request. Possible causes:
- `searchId` failed Zod validation
(not a valid ObjectId).
- The target search is not currently
archived and therefore cannot be unarchived.
'401':
description: |
Missing or invalid bearer token.
'403':
description: |
Bearer token lacks the `semantic:write` scope.
'404':
description: |
No archived search matches `searchId` within the caller's
org, or the row is already active / deleted.
'500':
description: |
Unexpected server error while unarchiving the search.
/agents:
get:
tags:
- Agents
summary: List agents
description: |
Retrieve a paginated list of agents available to the authenticated user.
**Overview**
Returns agents accessible through direct, team, or org-level permissions.
Search is performed across agent name, description, and tags. Sorting and
pagination are applied by the AI backend and the resulting envelope is
forwarded unchanged by the Node gateway.
**Gateway contract**
The Node route supports only these query params: `page`, `limit`, `search`,
`sort_by`, and `sort_order`.
The Python backend also understands `isDeleted`, but this gateway route
does not forward it, so it is not part of the public API contract here.
operationId: listAgents
security:
- bearerAuth: []
- oauth2:
- agent:read
parameters:
- in: query
name: page
required: false
schema:
type: integer
minimum: 1
default: 1
description: 1-based page number.
- in: query
name: limit
required: false
schema:
type: integer
minimum: 1
maximum: 200
default: 20
description: Maximum number of agents to return in the current page.
- in: query
name: search
required: false
schema:
type: string
minLength: 1
maxLength: 1000
description: Case-insensitive search across agent name, description, and tags. Leading/trailing whitespace is trimmed; blank-after-trim values are rejected.
- in: query
name: sort_by
required: false
schema:
type: string
minLength: 1
maxLength: 100
default: updatedAtTimestamp
description: Backend sort field. Leading/trailing whitespace is trimmed. Common value is `updatedAtTimestamp`.
- in: query
name: sort_order
required: false
schema:
type: string
enum:
- asc
- desc
default: desc
description: Sort direction.
responses:
'200':
description: Paginated list of accessible agents.
content:
application/json:
schema:
$ref: '#/components/schemas/AgentListResponse'
examples:
success:
summary: Example paginated response
value:
success: true
agents:
- _id: agentInstances/11111111-2222-3333-4444-555555555555
_key: 11111111-2222-3333-4444-555555555555
_rev: _exampleRev---
createdAtTimestamp: 1779792574728
createdBy: aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
description: AI agent for customer support workflows
isActive: true
isDeleted: false
isServiceAccount: false
models:
- 99999999-8888-7777-6666-555555555555_gpt-5.4-mini
name: Customer Support Agent
startMessage: Hello! How can I help you today?
systemPrompt: You are a helpful assistant.
tags: []
updatedAtTimestamp: 1779792574728
shareWithOrg: false
toolsets: []
knowledge: []
can_view: true
can_share: true
can_edit: true
can_delete: true
user_role: OWNER
access_type: INDIVIDUAL
pagination:
currentPage: 1
limit: 20
totalItems: 2
totalPages: 1
hasNext: false
hasPrev: false
'400':
description: Validation failed for one or more query params.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/agents/create:
post:
tags:
- Agents
summary: Create agent
description: |
Create a new custom AI agent.
**Overview:**
Agents are specialized AI assistants configured for specific tasks.
They can have custom system prompts, access to specific tools, and
be limited to certain knowledge bases.
**Agent Configuration:**
- **System prompt:** Instructions that define agent behavior
- **Tools:** Capabilities like web search, code execution, etc.
- **Knowledge bases:** Data sources the agent can access
- **Model config:** AI model settings (temperature, max tokens)
**Use Cases:**
- Customer support bot with product knowledge
- Code review assistant with repository access
- HR assistant with policy documents
operationId: createAgent
security:
- bearerAuth: []
- oauth2:
- agent:write
requestBody:
required: true
description: Request payload
content:
application/json:
schema:
$ref: '#/components/schemas/AgentCreateRequest'
responses:
'201':
description: Agent created
content:
application/json:
schema:
$ref: '#/components/schemas/AgentCreateResponse'
'400':
description: Invalid agent configuration
'401':
description: Unauthorized
/agents/{agentKey}:
get:
tags:
- Agents
summary: Get agent
description: |
Retrieve agent details by its unique key.
**Gateway not-found behavior:**
Unknown `agentKey`, lookup after soft-delete, and other AI-backend failures
that return 404 from the Python query service are surfaced by the Node
gateway as **HTTP 404** with an `ErrorResponse` body.
operationId: getAgent
security:
- bearerAuth: []
- oauth2:
- agent:read
parameters:
- name: agentKey
in: path
required: true
description: Unique agent identifier
schema:
type: string
minLength: 1
example: customer-support-agent
responses:
'200':
description: Agent details
content:
application/json:
schema:
$ref: '#/components/schemas/GetAgentResponse'
'401':
description: Missing or invalid bearer token (e.g. `No token provided`)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden — insufficient OAuth scope (`agent:read` required)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'400':
description: |
Gateway validation failure (non-empty `agentKey` path param) or missing
organization/user context on the authenticated request.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Agent not found, inaccessible, or previously deleted.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Unexpected AI-backend or gateway failure.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'503':
description: AI query service unreachable
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
put:
tags:
- Agents
summary: Update agent
description: |
Apply a partial update to an existing agent configuration.
**Gateway contract**
The Node gateway validates the request body via Zod middleware before
forwarding to the Python agent service. The `agentKey` path param and
the request body are both validated. Query parameters are ignored by
the controller.
**Update semantics**
Only fields present in the request body are updated. When `models` is
included, the gateway Zod middleware requires at least one model entry
and at least one object entry with `isReasoning: true`.
**Permissions**
The authenticated user must have `can_edit` on the agent (typically the
owner). Service-account and `shareWithOrg` transitions follow additional
Python business rules.
**Success response**
Returns a lightweight success envelope only. Use
`GET /agents/{agentKey}` to read the persisted agent after an update.
operationId: updateAgent
security:
- bearerAuth: []
- oauth2:
- agent:write
parameters:
- name: agentKey
in: path
required: true
description: Unique agent identifier
schema:
type: string
minLength: 1
example: customer-support-agent
requestBody:
required: true
description: Partial agent configuration fields to update
content:
application/json:
schema:
$ref: '#/components/schemas/AgentUpdateRequest'
responses:
'200':
description: Agent updated successfully
content:
application/json:
schema:
$ref: '#/components/schemas/AgentUpdateResponse'
'401':
description: Missing or invalid authentication
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden — insufficient OAuth scope (`agent:write` required)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'400':
description: |
Gateway validation failure. Returned for missing/invalid `agentKey`,
empty `models` array, `models` without a reasoning entry, malformed
JSON, and other Zod schema violations. Syntactically invalid JSON may
also surface as `500` depending on the Express parser.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Agent not found or inaccessible.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Unexpected AI-backend or gateway failure.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
delete:
tags:
- Agents
summary: Delete agent
description: |
Soft-delete an agent (tombstone) in the graph database.
**Overview:**
The Python query service marks the agent instance deleted inside a transaction.
List and search endpoints exclude tombstoned agents. Toolsets, tools, and
knowledge linked to the agent are not removed by this call.
**Permissions:**
Only the agent owner may delete (`can_delete` on the permission check).
**Warning:**
All conversations with this agent will become inaccessible.
**Gateway not-found behavior:**
Unknown `agentKey`, deleting an already-deleted agent, and `GET /agents/{agentKey}`
after delete return **HTTP 404** with an `ErrorResponse` body.
operationId: deleteAgent
security:
- bearerAuth: []
- oauth2:
- agent:write
parameters:
- name: agentKey
in: path
required: true
description: Unique agent identifier (gateway Zod requires non-empty string).
schema:
type: string
minLength: 1
example: customer-support-agent
responses:
'200':
description: Agent soft-deleted successfully
content:
application/json:
schema:
$ref: '#/components/schemas/AgentDeleteResponse'
'401':
description: Missing or invalid bearer token (e.g. `No token provided`)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Agent not found, inaccessible, or already deleted.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Unexpected AI-backend or gateway failure.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/agents/conversations/show/archives:
get:
tags:
- Agents
summary: List archived agent conversations grouped by agent
description: |
Returns archived agent conversations for the current user, grouped by
`agentKey`, with pagination over agent groups. Excludes conversations
whose agent was soft-deleted upstream.
operationId: listAgentArchivedConversationsGrouped
security:
- bearerAuth: []
- oauth2:
- agent:read
parameters:
- name: agentPage
in: query
required: false
schema:
type: integer
minimum: 1
default: 1
- name: agentLimit
in: query
required: false
schema:
type: integer
minimum: 1
maximum: 100
default: 5
responses:
'200':
description: Grouped archived conversations
content:
application/json:
schema:
$ref: '#/components/schemas/AgentArchivedGroupsResponse'
'401':
description: Unauthorized
/agents/{agentKey}/conversations/show/archives:
get:
tags:
- Agents
summary: List archived conversations for an agent
description: Paginated list of archived conversations for the given agent key.
operationId: listAgentConversationArchives
security:
- bearerAuth: []
- oauth2:
- agent:read
parameters:
- name: agentKey
in: path
required: true
schema:
type: string
- name: page
in: query
schema:
type: integer
minimum: 1
default: 1
- name: limit
in: query
schema:
type: integer
minimum: 1
maximum: 100
default: 20
- name: sortBy
in: query
schema:
type: string
enum:
- createdAt
- lastActivityAt
- title
- name: sortOrder
in: query
schema:
type: string
enum:
- asc
- desc
- name: search
in: query
schema:
type: string
maxLength: 1000
- name: startDate
in: query
schema:
type: string
format: date-time
- name: endDate
in: query
schema:
type: string
format: date-time
responses:
'200':
description: Archived conversations for the agent
content:
application/json:
schema:
$ref: '#/components/schemas/AgentArchivedConversationListResponse'
'400':
description: Invalid query parameters (gateway validation)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Unauthorized
/agents/{agentKey}/conversations/attachments/upload:
post:
tags:
- Agents
summary: Upload agent chat attachments
description: |
Multipart upload of PDF, JPEG, or PNG files for agent chat. Same limits as assistant
chat (`POST /conversations/attachments/upload`): up to 10 files, 5 MiB each. Proxies to
the AI backend. Optional `conversationId` associates uploads with an existing agent thread.
operationId: uploadAgentConversationChatAttachments
security:
- bearerAuth: []
- oauth2:
- agent:execute
parameters:
- name: agentKey
in: path
required: true
schema:
type: string
minLength: 1
requestBody:
required: true
description: Multipart form with attachment files and optional `conversationId`.
content:
multipart/form-data:
schema:
type: object
required:
- files
properties:
conversationId:
type: string
pattern: ^$|^[0-9a-fA-F]{24}$
description: |
Optional existing agent conversation id. Empty string is treated as unset; any non-empty value must be a 24-character ObjectId.
files:
type: array
minItems: 1
maxItems: 10
description: |
One or more files; field name must be `files`. Accepted MIME types: `application/pdf`, `image/jpeg`, `image/jpg`, `image/png`. Max 5 MiB each.
items:
type: string
format: binary
x-speakeasy-name-override: File
responses:
'200':
description: |
Success. The gateway proxies the AI-backend JSON envelope after transforming the multipart upload into the backend attachment payload.
content:
application/json:
schema:
$ref: '#/components/schemas/ChatAttachmentUploadResponse'
'400':
description: |
Invalid `conversationId`, no files, unsupported MIME type (not PDF/JPEG/PNG), or Multer rejection (e.g. file too large).
'401':
description: Unauthorized
'403':
description: Missing `agent:execute` scope
'500':
description: |
Gateway fallback when the upstream call does not return a status (implementation default).
/agents/{agentKey}/conversations/attachments/{recordId}:
delete:
tags:
- Agents
summary: Delete an agent chat attachment
description: |
Deletes a previously uploaded attachment by proxying `DELETE` to the query service
(`/api/v1/chat/attachments/{recordId}`). The Node handler always ends the response **without
a JSON body** on success (empty body); the **status code** is the upstream status, or **204**
if none is returned.
On validation failure in the gateway (invalid / blank path params), the response is **400**
with a small JSON error object. Same fire-and-forget semantics as
`DELETE /conversations/attachments/{recordId}` on the client.
operationId: deleteAgentConversationChatAttachment
security:
- bearerAuth: []
- oauth2:
- agent:execute
parameters:
- name: agentKey
in: path
required: true
description: Agent key path parameter. Must be non-empty.
schema:
type: string
minLength: 1
- name: recordId
in: path
required: true
description: Attachment record id (from the upload response). Must be non-blank after trim.
schema:
type: string
minLength: 1
responses:
'204':
description: Success with no content (typical when upstream returns 204).
'400':
description: Invalid or blank path params (`agentKey` or `recordId`).
content:
application/json:
schema:
type: object
additionalProperties: false
required:
- error
properties:
error:
type: string
example: recordId is required
'401':
description: Unauthorized
'403':
description: Missing `agent:execute` scope
default:
description: |
Other status codes are forwarded from the query service (e.g. 404) with an **empty** response body from this route.
/agents/{agentKey}/conversations/stream:
post:
tags:
- Agents
summary: Create agent conversation with streaming response
description: |
Start a new conversation with the specified agent and stream the AI
response as Server-Sent Events (SSE). The first user message is saved
and forwarded to the upstream agent backend; subsequent tokens, tool
calls, and lifecycle events are emitted on the open SSE connection.
operationId: streamAgentConversation
security:
- bearerAuth: []
- oauth2:
- agent:execute
parameters:
- name: agentKey
in: path
required: true
description: Stable key identifying the agent that owns this conversation.
schema:
type: string
minLength: 1
requestBody:
required: true
description: Initial turn payload for the new agent conversation stream.
content:
application/json:
schema:
$ref: '#/components/schemas/AgentStreamCreateConversationRequest'
responses:
'200':
description: SSE stream (text/event-stream)
content:
text/event-stream:
schema:
$ref: '#/components/schemas/AgentStreamSSEEvent'
'400':
description: Invalid request body
'401':
description: Unauthorized
/agents/{agentKey}/conversations/{conversationId}/messages/stream:
post:
tags:
- Agents
summary: Add message to agent conversation with streaming response
description: |
Append a user message to an existing agent conversation and stream the
assistant reply over SSE.
operationId: streamAgentConversationMessage
security:
- bearerAuth: []
- oauth2:
- agent:execute
parameters:
- name: agentKey
in: path
required: true
schema:
type: string
- name: conversationId
in: path
required: true
schema:
type: string
format: objectId
requestBody:
required: true
description: Follow-up message payload for the agent conversation stream.
content:
application/json:
schema:
$ref: '#/components/schemas/AgentAddMessageStreamRequest'
responses:
'200':
description: SSE stream (text/event-stream)
content:
text/event-stream:
schema:
$ref: '#/components/schemas/AgentMessageStreamSSEEvent'
'400':
description: Invalid request body
'401':
description: Unauthorized
'404':
description: Conversation not found
/agents/{agentKey}/conversations/{conversationId}/message/{messageId}/regenerate:
post:
tags:
- Agents
summary: Regenerate agent conversation message
description: |
Regenerate the AI response for a specific message in an agent
conversation and stream the new answer over Server-Sent Events.
**Constraints:**
- Only the last message in the conversation can be regenerated.
- The target message must be of type `bot_response`.
**Request body:**
All request-body fields are optional. When omitted, the server reuses
the original model/context. The body supports:
- `filters`
- `chatMode`
- `modelKey`
- `modelName`
- `modelFriendlyName`
- `timezone`
- `currentTime`
- `tools`
**Streaming behavior:**
The response is delivered as `text/event-stream`. Stable events are
`connected`, `complete`, and `error`. Additional agent/tool lifecycle
events may be forwarded by the backend and should be treated as
informational updates.
Validation failures on params/body are returned as normal HTTP `400`
responses before the stream starts. Valid-shape requests that fail
conversation lookup or regenerate rules are reported as SSE `error`
events after stream initialization.
operationId: regenerateAgentConversationMessage
security:
- bearerAuth: []
- oauth2:
- agent:execute
parameters:
- name: agentKey
in: path
required: true
description: Stable key identifying the agent that owns this conversation.
schema:
type: string
minLength: 1
- name: conversationId
in: path
required: true
description: ID of the agent conversation containing the target message.
schema:
type: string
format: objectId
- name: messageId
in: path
required: true
description: ID of the bot-response message to regenerate.
schema:
type: string
format: objectId
requestBody:
required: false
description: |
Optional regeneration payload. All fields are optional and are
validated against `RegenerateRequest`.
content:
application/json:
schema:
$ref: '#/components/schemas/RegenerateRequest'
responses:
'200':
description: |
SSE stream established.
Stable event names:
- `connected` — confirms the stream is open
- `complete` — returns the updated conversation plus metadata
- `error` — reports lookup failures, authorization failures on
the conversation, or regenerate-rule failures after the stream
has started
Additional backend-defined agent/tool events may be emitted.
Clients should ignore unknown event names.
content:
text/event-stream:
schema:
$ref: '#/components/schemas/AgentRegenerateSSEEvent'
'400':
description: |
Validation failed for path parameters or request body. Common
causes include invalid ObjectId formats, empty strings for fields
that require content, malformed `filters`, invalid `tools`
entries, or `currentTime` values that are not ISO 8601 datetimes
with offset information.
'401':
description: Unauthorized
/agents/{agentKey}/conversations/{conversationId}/message/{messageId}/feedback:
post:
tags:
- Agents
summary: Submit feedback for an agent message
description: |
Append structured feedback to a bot-response message in an agent
conversation. Uses the same request body shape as
`updateMessageFeedback` (helpfulness, categories, comments). Feedback
can only be submitted on `bot_response` messages.
operationId: updateAgentConversationMessageFeedback
security:
- bearerAuth: []
- oauth2:
- agent:execute
parameters:
- name: agentKey
in: path
required: true
description: Unique agent identifier (gateway Zod requires non-empty string).
schema:
type: string
minLength: 1
- name: conversationId
in: path
required: true
description: Unique conversation identifier.
schema:
type: string
format: objectId
- name: messageId
in: path
required: true
description: Identifier of the bot-response message being rated.
schema:
type: string
format: objectId
requestBody:
required: true
description: Feedback payload for the agent message.
content:
application/json:
schema:
$ref: '#/components/schemas/MessageFeedbackSubmitRequest'
responses:
'200':
description: Feedback stored
content:
application/json:
schema:
$ref: '#/components/schemas/MessageFeedbackUpdateResponse'
'400':
description: |
Invalid request. Possible causes:
- Feedback target is not a `bot_response` message.
- A `categories` value is not in the allowed list.
- `conversationId` or `messageId` is not a valid ObjectId.
'401':
description: Unauthorized
'404':
description: Conversation or message not found
'500':
description: Persistence layer failed to append the feedback entry.
/agents/{agentKey}/conversations/{conversationId}/archive:
post:
tags:
- Agents
summary: Archive an agent conversation
description: Marks the conversation as archived for the authenticated owner.
operationId: archiveAgentConversation
security:
- bearerAuth: []
- oauth2:
- agent:write
parameters:
- name: agentKey
in: path
required: true
schema:
type: string
- name: conversationId
in: path
required: true
schema:
type: string
format: objectId
responses:
'200':
description: Conversation archived
content:
application/json:
schema:
$ref: '#/components/schemas/AgentConversationArchiveResponse'
'400':
description: |
Invalid path input or the conversation is already archived.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Conversation not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/agents/{agentKey}/conversations/{conversationId}/unarchive:
post:
tags:
- Agents
summary: Unarchive an agent conversation
description: Restores an archived agent conversation to the active list.
operationId: unarchiveAgentConversation
security:
- bearerAuth: []
- oauth2:
- agent:write
parameters:
- name: agentKey
in: path
required: true
schema:
type: string
- name: conversationId
in: path
required: true
schema:
type: string
format: objectId
responses:
'200':
description: Conversation unarchived
content:
application/json:
schema:
$ref: '#/components/schemas/AgentConversationUnarchiveResponse'
'400':
description: |
Invalid path input or the conversation is not currently archived.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Conversation not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/agents/{agentKey}/conversations/{conversationId}/title:
patch:
tags:
- Agents
summary: Update agent conversation title
description: |
Updates the display title for an agent conversation owned by the caller.
The controller looks up the conversation by `_id`, `orgId`, `userId`,
`agentKey`, and `isDeleted: false`.
The request body uses the shared title validator (`1..200` chars), and
the controller trims the incoming title before saving it. A whitespace-only
title can therefore still return HTTP 400 even if the raw string is
non-empty.
operationId: updateAgentConversationTitle
security:
- bearerAuth: []
- oauth2:
- agent:write
parameters:
- name: agentKey
in: path
required: true
schema:
type: string
- name: conversationId
in: path
required: true
schema:
type: string
format: objectId
requestBody:
required: true
description: |
New title for the agent conversation.
The server trims the provided string before saving it.
content:
application/json:
schema:
$ref: '#/components/schemas/ConversationTitleUpdateRequest'
responses:
'200':
description: Title updated successfully
content:
application/json:
schema:
$ref: '#/components/schemas/AgentConversationTitleUpdateResponse'
'400':
description: |
Invalid path or body input.
This includes Zod validation failures for malformed `conversationId`
or invalid `title` payloads, plus controller-level bad requests such
as titles that become empty after trimming.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: |
Agent conversation not found for the authenticated user, organization,
and agent scope, or the conversation is soft-deleted.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/agents/{agentKey}/conversations/{conversationId}:
delete:
tags:
- Agents
summary: Delete an agent conversation
description: |
Soft-deletes an agent conversation owned by the authenticated user.
The controller scopes the lookup by `_id`, `orgId`, `userId`, and
`agentKey`. If no matching writable conversation is found, the route is
intentionally a no-op and still returns HTTP 200 with `conversation: null`.
This makes the operation idempotent:
- deleting a nonexistent conversation returns success with `null`
- deleting through a different `agentKey` returns success with `null`
- deleting an already deleted conversation returns success with `null`
operationId: deleteAgentConversationById
security:
- bearerAuth: []
- oauth2:
- agent:write
parameters:
- name: agentKey
in: path
required: true
schema:
type: string
- name: conversationId
in: path
required: true
schema:
type: string
format: objectId
responses:
'200':
description: Conversation deleted or no-op delete completed successfully
content:
application/json:
schema:
$ref: '#/components/schemas/AgentConversationDeleteResponse'
'400':
description: Invalid path input
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal server error while deleting the agent conversation
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
get:
tags:
- Agents
summary: Get agent conversation by ID
description: |
Returns the conversation with paginated/sorted messages and filter metadata.
**Message Pagination:**
Messages are paginated newest-first: `page=1` returns the most recent
batch. Increment `page` to load older batches (used by the infinite-scroll
"load older messages" feature).
- `page`: Page number (default: 1)
- `limit`: Messages per page (default: 20, max: 100)
operationId: getAgentConversationById
security:
- bearerAuth: []
- oauth2:
- agent:read
parameters:
- name: agentKey
in: path
required: true
schema:
type: string
- name: conversationId
in: path
required: true
schema:
type: string
format: objectId
- name: page
in: query
description: Page number for message pagination (1 = most recent batch)
schema:
type: integer
minimum: 1
default: 1
- name: limit
in: query
description: Number of messages per page
schema:
type: integer
minimum: 1
maximum: 100
default: 20
- name: sortBy
in: query
description: Field to sort messages by
schema:
type: string
enum:
- createdAt
- messageType
- content
default: createdAt
- name: sortOrder
in: query
description: Sort direction
schema:
type: string
enum:
- asc
- desc
default: desc
- name: startDate
in: query
description: Filter messages created on or after this date
schema:
type: string
format: date-time
- name: endDate
in: query
description: Filter messages created on or before this date
schema:
type: string
format: date-time
- name: messageType
in: query
description: Filter messages by type
schema:
type: string
enum:
- user_query
- bot_response
- error
- feedback
- system
responses:
'200':
description: Agent conversation detail
content:
application/json:
schema:
$ref: '#/components/schemas/AgentConversationDetailResponse'
'401':
description: Unauthorized
'404':
description: Conversation not found
/agents/{agentKey}/conversations:
get:
tags:
- Agents
summary: List agent conversations
description: |
Paginated list of conversations for the agent (owned and shared-with-me),
excluding archived threads.
operationId: listAgentConversations
security:
- bearerAuth: []
- oauth2:
- agent:read
parameters:
- name: agentKey
in: path
required: true
description: Agent identifier used to scope the conversation list.
schema:
type: string
- name: page
in: query
description: 1-based page number. Defaults to `1`.
schema:
type: integer
minimum: 1
default: 1
- name: limit
in: query
description: Page size. Defaults to `20`; maximum `100`.
schema:
type: integer
minimum: 1
maximum: 100
default: 20
- name: sortBy
in: query
description: |
Preferred sort field. Supported values are `createdAt`,
`lastActivityAt`, and `title`.
The current gateway validator preserves legacy behavior: unsupported
values are accepted but ignored, and the handler falls back to
`lastActivityAt`.
schema:
type: string
- name: sortOrder
in: query
description: |
Preferred sort direction. Supported values are `asc` and `desc`.
The current gateway validator preserves legacy behavior: unsupported
values are accepted but ignored, and the handler falls back to
descending order.
schema:
type: string
- name: search
in: query
description: |
Case-insensitive search term applied to conversation `title` and
`messages.content`. Maximum length is 1000 characters. HTML/XSS
payloads and format specifiers are rejected.
schema:
type: string
maxLength: 1000
- name: startDate
in: query
description: |
Inclusive lower bound on `createdAt`. The handler accepts any
JavaScript-parseable date string; invalid values return HTTP 400.
schema:
type: string
example: '2026-05-26T00:00:00.000Z'
- name: endDate
in: query
description: |
Inclusive upper bound on `createdAt`. The handler accepts any
JavaScript-parseable date string; invalid values return HTTP 400.
schema:
type: string
example: '2026-05-27T00:00:00.000Z'
- name: status
in: query
description: |
Optional status filter applied to the `sharedWithMeConversations`
branch of the response. The main `conversations` list ignores this
parameter.
schema:
type: string
- name: isArchived
in: query
description: |
Optional archived flag applied to the `sharedWithMeConversations`
branch before the route-level non-archived guard is enforced.
Accepted values are `true` and `false`.
schema:
type: string
enum:
- 'true'
- 'false'
responses:
'200':
description: Conversation list
content:
application/json:
schema:
$ref: '#/components/schemas/AgentConversationListResponse'
'400':
description: |
Invalid path or query parameter.
This includes Zod validation failures such as invalid pagination,
invalid booleans, malformed date values, duplicate `search`
parameters, or overlong / invalid `search` input.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/configurationManager/ai-models/available/{modelType}:
get:
tags:
- AI Models Providers
summary: Get available models by type
description: |
Returns a **flattened list** of individual AI models of the requested type,
suitable for use in selection dropdowns and model-picker UIs.
Each provider configuration entry may specify multiple comma-separated model
names; this endpoint expands those into one object per model name so callers
receive a flat, enumerable collection.
**Flattening rules:**
- Only the **first** model in a multi-model provider entry is marked
`isDefault: true`; all subsequent models from the same entry get `false`.
- `modelFriendlyName` is included **only** when the provider entry contains
exactly one model name (not a comma-separated list).
- When no providers of the requested type are configured the endpoint still
returns HTTP **200** with an empty `models` array — this is **not** an error.
**Access control:** requires a valid bearer token. For OAuth tokens the
`config:read` scope must be present; regular JWT bearer tokens pass through
without scope enforcement.
operationId: getAvailableModelsByType
security:
- bearerAuth: []
- oauth2:
- config:read
parameters:
- name: modelType
in: path
required: true
description: |
Category of AI model to retrieve.
Must be one of: `llm`, `embedding`, `ocr`, `slm`, `reasoning`, `multiModal`, `imageGeneration`, `tts`, `stt`.
schema:
$ref: '#/components/schemas/ModelType'
responses:
'200':
description: |
Available models retrieved successfully.
An empty `models` array (with HTTP 200) is returned when no providers of
the requested type have been configured — treat this as a valid, empty
state, not an error.
content:
application/json:
schema:
type: object
required:
- status
- models
- message
properties:
status:
type: string
enum:
- success
example: success
message:
type: string
description: |-
Human-readable summary. Two formats are possible:
- `"Found {n} {modelType} models"` — the `modelType` key
exists in the stored config (returned even when `n` is 0,
e.g. `"Found 0 ocr models"`).
- `"No {modelType} models found"` — no AI config has been
stored yet, or the `modelType` key is absent from the
stored config entirely.
example: Found 2 llm models
models:
type: array
description: Flat list of individual model entries. Each entry represents one model name from one provider configuration.
items:
type: object
required:
- modelType
- provider
- modelName
- modelKey
- isMultimodal
- isReasoning
- isDefault
properties:
modelType:
allOf:
- $ref: '#/components/schemas/ModelType'
description: Model category — always matches the `{modelType}` path parameter.
provider:
type: string
description: Provider identifier as stored in configuration (e.g. `openAI`, `azureOpenAI`, `anthropic`, `gemini`, `ollama`).
example: azureOpenAI
modelName:
type: string
description: Specific model name/identifier forwarded to the provider API when making inference calls.
example: gpt-5.4-mini
modelKey:
type: string
format: uuid
description: UUID that uniquely identifies the provider configuration entry this model was expanded from. Use this key when calling update/delete endpoints.
example: f3a4b5b6-5b6c-4e85-9097-3202cfe696fc
isMultimodal:
type: boolean
description: '`true` when this model accepts multi-modal inputs (text + images). Always present; defaults to `false` when not explicitly set.'
example: true
isReasoning:
type: boolean
description: '`true` when this is a reasoning / chain-of-thought model. Always present; defaults to `false` when not explicitly set.'
example: true
isDefault:
type: boolean
description: '`true` for the first model in the provider entry that was marked as default. At most one entry per `modelType` will have this set to `true`.'
example: true
modelFriendlyName:
type: string
description: Optional human-readable display name. Only present when the provider configuration entry contains exactly one model name (not a comma-separated list) **and** a friendly name was added during configuration.
example: Reasoning model
examples:
two_llm_models:
summary: Two LLM models from an Azure OpenAI provider
value:
status: success
message: Found 2 llm models
models:
- modelType: llm
provider: azureOpenAI
modelName: gpt-5.4-mini
modelKey: f3a4b5b6-5b6c-4e85-9097-3202cfe696fc
isMultimodal: true
isReasoning: true
isDefault: true
- modelType: llm
provider: azureOpenAI
modelName: gpt-5.4
modelKey: 7af8d3a7-ad2e-43a1-8716-ae95e4fbc888
isMultimodal: true
isReasoning: true
isDefault: false
modelFriendlyName: Reasoning model
no_models_configured:
summary: modelType key present in config but zero models after expansion
value:
status: success
message: Found 0 ocr models
models: []
'400':
description: |
Invalid `modelType` path parameter.
The `modelType` value was not one of the supported enum categories.
This response is produced by the Zod validation middleware **before**
the handler runs. The `error.metadata.errors` array contains
per-field detail about exactly which constraint failed.
content:
application/json:
schema:
type: object
required:
- error
properties:
error:
type: object
required:
- code
- message
- metadata
properties:
code:
type: string
enum:
- VALIDATION_ERROR
example: VALIDATION_ERROR
message:
type: string
example: Validation failed
metadata:
type: object
required:
- errors
description: Per-field validation detail from Zod.
properties:
errors:
type: array
items:
type: object
required:
- field
- message
- code
- value
properties:
field:
type: string
description: Dot-separated path to the failing field within the request (params, body, query).
example: params.modelType
message:
type: string
description: Human-readable Zod validation message.
example: Invalid enum value. Expected 'ocr' | 'embedding' | 'llm' | 'slm' | 'reasoning' | 'multiModal' | 'imageGeneration' | 'tts' | 'stt', received 'llmr'
code:
type: string
description: Machine-readable error code mapped from the Zod issue code.
enum:
- INVALID_TYPE
- INVALID_LITERAL
- INVALID_ENUM
- INVALID_UNION
- INVALID_DISCRIMINATOR
- INVALID_ARGUMENTS
- TOO_SMALL
- TOO_BIG
example: INVALID_ENUM
value:
type: string
description: The rejected value stringified. May be an empty string when the value is not easily serialisable.
example: ''
example:
error:
code: VALIDATION_ERROR
message: Validation failed
metadata:
errors:
- field: params.modelType
message: Invalid enum value. Expected 'ocr' | 'embedding' | 'llm' | 'slm' | 'reasoning' | 'multiModal' | 'imageGeneration' | 'tts' | 'stt', received 'llmr'
code: INVALID_ENUM
value: ''
'401':
description: |
Missing or invalid authentication token.
The bearer token was absent, expired, malformed, or could not be
verified by the auth middleware.
content:
application/json:
schema:
type: object
required:
- error
properties:
error:
type: object
required:
- code
- message
properties:
code:
type: string
enum:
- HTTP_UNAUTHORIZED
example: HTTP_UNAUTHORIZED
message:
type: string
example: Invalid token
example:
error:
code: HTTP_UNAUTHORIZED
message: Invalid token
'403':
description: |
Insufficient OAuth scope.
Only applies to OAuth tokens. The token did not carry the `config:read`
scope required by this endpoint. Regular (non-OAuth) JWT bearer tokens
are not subject to scope enforcement and will not receive this error.
content:
application/json:
schema:
type: object
required:
- error
properties:
error:
type: object
required:
- code
- message
properties:
code:
type: string
enum:
- HTTP_FORBIDDEN
example: HTTP_FORBIDDEN
message:
type: string
example: 'Insufficient scope. Required: config:read'
example:
error:
code: HTTP_FORBIDDEN
message: 'Insufficient scope. Required: config:read'
'500':
description: An unexpected error occurred on the server.
content:
application/json:
schema:
type: object
required:
- error
properties:
error:
type: object
required:
- code
- message
properties:
code:
type: string
enum:
- HTTP_INTERNAL_SERVER_ERROR
example: HTTP_INTERNAL_SERVER_ERROR
message:
type: string
example: An unexpected error occurred
example:
error:
code: HTTP_INTERNAL_SERVER_ERROR
message: An unexpected error occurred
/configurationManager/web-search:
get:
tags:
- Web Search
summary: Get all web search providers
description: |
Retrieve all configured web search providers and current web search settings.
**Authentication:** Session JWT or OAuth 2.0 access token via `Authorization: Bearer`.
OAuth tokens must include the `config:read` scope. Admin role is not required.
operationId: getWebSearchProviders
security:
- bearerAuth: []
- oauth2:
- config:read
responses:
'200':
description: Web search providers and settings retrieved
content:
application/json:
schema:
$ref: '#/components/schemas/WebSearchProvidersResponse'
'401':
description: Missing or invalid Bearer token
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden — OAuth token missing `config:read` scope
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'