Skip to content

Latest commit

 

History

History
1456 lines (1039 loc) · 36.4 KB

File metadata and controls

1456 lines (1039 loc) · 36.4 KB

API Reference

Part of Connapse — open-source AI knowledge management platform.

Connapse exposes multiple API surfaces for programmatic access:

  1. REST API — HTTP endpoints for containers, files, search, auth, and settings
  2. MCP (Model Context Protocol) — Tool interface for AI agents
  3. CLI — Command-line interface (connapse)

REST API

Base URL (development): https://localhost:5001

All endpoints return JSON. Errors follow RFC 7807 Problem Details format.

Authentication

Connapse uses a multi-tier authentication system:

Tier Header / Mechanism Used By Lifetime
Cookie ASP.NET Core Identity cookie Blazor UI (browser sessions) 14-day sliding
OAuth 2.1 Authorization: Bearer <token> (via PKCE) CLI (browser-based login) 60-90 min + refresh token
PAT X-Api-Key: cnp_<token> REST API clients, scripts, automation Until revoked
JWT Bearer Authorization: Bearer <token> SDK clients, external integrations 60-90 min + refresh

Role-based access control (RBAC):

Role Permissions
Admin Full access: all endpoints, user management, settings, agents
Editor Upload, delete, search, manage containers and folders
Viewer Search and browse only (no writes)
Agent MCP tool access only (search + ingest via API keys)

First-time setup: On a fresh install with no users, visit the login page — it automatically shows an admin account creation form. The first user becomes the system admin.

Subsequent users are invite-only. Admins create invitations at /admin/users. Invited users visit /register?token=<token> to set their password.


Pagination

All list endpoints use paginated responses. Pagination parameters are required — omitting them returns 400.

Query Parameters:

Parameter Type Default Constraints
skip int 0 min: 0
take int 50 min: 1, max: 200

Response Envelope (PagedResponse<T>):

{
  "items": [ ... ],
  "totalCount": 142,
  "hasMore": true
}
Field Description
items Array of results for the current page
totalCount Total number of matching records
hasMore true if more records exist beyond skip + take

Paginated endpoints: GET /api/containers, GET /api/containers/{id}/files, GET /api/v1/auth/users.

Example: GET /api/containers?skip=0&take=20


Auth API

Base path: /api/v1/auth

Get JWT Token

Exchange email + password for a JWT access/refresh token pair.

Endpoint: POST /api/v1/auth/token

Request Body:

{
  "email": "admin@example.com",
  "password": "YourSecurePassword"
}

Response (200 OK):

{
  "accessToken": "eyJhbGci...",
  "refreshToken": "dGhpcyBpcyBhIHJlZnJlc2g...",
  "expiresIn": 5400,
  "tokenType": "Bearer"
}

Response (401 Unauthorized): Invalid credentials.

Notes:

  • Use the accessToken as Authorization: Bearer <token> on subsequent requests
  • refreshToken can be exchanged for a new token pair before expiry
  • Updates LastLoginAt on the user record + writes audit log entry

Refresh JWT Token

Exchange a valid refresh token for a new access/refresh token pair.

Endpoint: POST /api/v1/auth/token/refresh

Request Body:

{
  "refreshToken": "dGhpcyBpcyBhIHJlZnJlc2g..."
}

Response (200 OK): Same as POST /api/v1/auth/token.

Response (401 Unauthorized): Token invalid, expired, or already revoked.

Notes: Old refresh token is revoked on use (rotation). Each call issues a new pair.


List Personal Access Tokens

Endpoint: GET /api/v1/auth/pats

Auth: Required (any authenticated user)

Response (200 OK):

[
  {
    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "name": "CLI (LAPTOP-01)",
    "prefix": "cnp_abc123",
    "lastUsedAt": "2026-02-26T10:00:00Z",
    "expiresAt": null,
    "isRevoked": false,
    "createdAt": "2026-02-20T09:00:00Z"
  }
]

Create Personal Access Token

Endpoint: POST /api/v1/auth/pats

Auth: Required (any authenticated user)

Request Body:

{
  "name": "My Script Token",
  "expiresAt": "2027-01-01T00:00:00Z"
}

Fields:

  • name (required): Display label
  • expiresAt (optional): ISO 8601 datetime; if omitted, token never expires

Response (200 OK):

{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "name": "My Script Token",
  "token": "cnp_<random-64-chars>",
  "expiresAt": "2027-01-01T00:00:00Z"
}

Important: The token value is shown once only. Store it securely immediately.


Revoke Personal Access Token

Endpoint: DELETE /api/v1/auth/pats/{id}

Auth: Required (own tokens only; admins can revoke any)

Response (204 No Content)


OAuth 2.1 Endpoints

Connapse implements OAuth 2.1 with PKCE for CLI and third-party client authentication. These endpoints follow RFC 6749 and RFC 7636.

Discovery

Endpoint Purpose
GET /.well-known/oauth-protected-resource Protected resource metadata (resource URL, supported scopes)
GET /.well-known/oauth-authorization-server Authorization server metadata (endpoints, supported grants, PKCE methods)

CLI Client Metadata

GET /oauth/clients/cli.json — Static metadata document for the built-in CLI client. Returns the client ID, allowed redirect URIs, and grant types.

Authorization

GET /oauth/authorize — Renders the OAuth consent page. The user authenticates (or is already authenticated via cookie) and approves the requested scopes.

Query Parameters:

Parameter Required Description
response_type Yes Must be code
client_id Yes Client ID (URL to metadata document, or registered ID)
redirect_uri Yes Must match a registered redirect URI
code_challenge Yes PKCE code challenge (S256)
code_challenge_method Yes Must be S256
state Recommended CSRF protection value
scope Optional Space-separated scopes (e.g., knowledge:read knowledge:write)
resource Optional Resource indicator (RFC 8707)

Token Exchange

POST /oauth/token — Exchange an authorization code or refresh token for an access token.

Content-Type: application/x-www-form-urlencoded (required)

Grant type authorization_code:

Parameter Required Description
grant_type Yes authorization_code
code Yes Authorization code from the consent page redirect
redirect_uri Yes Must match the original authorize request
client_id Yes Client ID
code_verifier Yes PKCE code verifier

Grant type refresh_token:

Parameter Required Description
grant_type Yes refresh_token
refresh_token Yes The refresh token to exchange
client_id Optional If provided, must match the original grant's client

Response (200 OK):

{
  "access_token": "eyJhbGci...",
  "token_type": "bearer",
  "expires_in": 5400,
  "refresh_token": "new-refresh-token...",
  "scope": "knowledge:read knowledge:write"
}

Notes:

  • Refresh tokens are rotated on each use (old token is revoked)
  • Replay detection: reusing a consumed refresh token revokes the entire token family
  • The resource parameter in the authorize request is validated against the server's base URL

Dynamic Client Registration

POST /oauth/register — Register a new OAuth client dynamically.

Request Body:

{
  "client_name": "My App",
  "redirect_uris": ["http://127.0.0.1:9999/callback"],
  "application_type": "native"
}

Response (201 Created):

{
  "client_id": "generated-client-id",
  "client_name": "My App",
  "redirect_uris": ["http://127.0.0.1:9999/callback"],
  "grant_types": ["authorization_code", "refresh_token"],
  "application_type": "native",
  "token_endpoint_auth_method": "none"
}

Supported scopes: knowledge:read, knowledge:write


List Users (Admin)

Endpoint: GET /api/v1/auth/users?skip=0&take=50

Auth: Admin role required

Query Parameters: skip, take (see Pagination)

Response (200 OK):

{
  "items": [
    {
      "id": "user-guid",
      "email": "viewer@example.com",
      "roles": ["Viewer"],
      "isSystemAdmin": false,
      "lastLoginAt": "2026-02-25T14:30:00Z",
      "createdAt": "2026-02-20T09:00:00Z"
    }
  ],
  "totalCount": 1,
  "hasMore": false
}

Assign User Roles (Admin)

Endpoint: PUT /api/v1/auth/users/{id}/roles

Auth: Admin role required

Request Body:

{
  "roles": ["Editor"]
}

Notes:

  • Owner role cannot be assigned or removed via this endpoint
  • Agent role cannot be assigned to user accounts (use Agent API instead)

Response (200 OK)


Agents API

Base path: /api/v1/agents

All agent endpoints require Admin role.

Agents are non-human identities (CI/CD pipelines, automation scripts) that authenticate via API keys and access the MCP server. For details on what agent API keys can access, see Agent Permissions and Scope.

List Agents

Endpoint: GET /api/v1/agents

Response (200 OK):

[
  {
    "id": "agent-guid",
    "name": "CI Pipeline",
    "description": "Indexes docs on every merge",
    "isEnabled": true,
    "activeKeyCount": 2,
    "createdAt": "2026-02-20T09:00:00Z"
  }
]

Create Agent

Endpoint: POST /api/v1/agents

Request Body:

{
  "name": "CI Pipeline",
  "description": "Indexes docs on every merge"
}

Response (200 OK): Returns the created Agent object.


Get Agent

Endpoint: GET /api/v1/agents/{id}

Response (200 OK | 404 Not Found)


Enable/Disable Agent

Endpoint: PUT /api/v1/agents/{id}/active

Request Body:

{ "isEnabled": false }

Response (200 OK)


Delete Agent

Endpoint: DELETE /api/v1/agents/{id}

Deletes the agent and all its API keys.

Response (204 No Content)


List Agent API Keys

Endpoint: GET /api/v1/agents/{id}/keys

Response (200 OK):

[
  {
    "id": "key-guid",
    "name": "Production Key",
    "prefix": "cnp_abc123",
    "lastUsedAt": "2026-02-26T08:00:00Z",
    "isRevoked": false,
    "createdAt": "2026-02-20T09:00:00Z"
  }
]

Create Agent API Key

Endpoint: POST /api/v1/agents/{id}/keys

Request Body:

{ "name": "Production Key" }

Response (200 OK):

{
  "id": "key-guid",
  "name": "Production Key",
  "token": "cnp_<random-64-chars>"
}

Important: The token is shown once only. Store it securely immediately.


Revoke Agent API Key

Endpoint: DELETE /api/v1/agents/{agentId}/keys/{keyId}

Response (204 No Content)


Agent Permissions and Scope

Agents are MCP-only identities. They authenticate with cnp_-prefixed API keys and interact with Connapse exclusively through the MCP endpoint. Agent keys cannot access REST API endpoints.

Access surface

Interface Access Details
MCP (POST /mcp) Allowed All 11 MCP tools available
REST API (/api/v1/*) 403 Forbidden Agent role is not included in REST API authorization policies (Viewer/Editor/Admin)
Web UI Not accessible Agent keys are API-only

This is by design. Agents interact exclusively through the MCP protocol, which provides a structured tool interface suited to non-human consumers. REST API endpoints use role-based policies (Viewer, Editor, Admin) that do not include the Agent role.

Implicit scopes

When an agent authenticates via API key, it receives two implicit scopes. These scopes govern MCP tool behavior only — they do not grant REST API access.

Scope Grants
knowledge:read Search and read documents across all containers via MCP
agent:ingest Upload and delete files via MCP (subject to connector write guards)

Agents have unrestricted access to all containers in the system. There is no per-container access control for agent API keys.

MCP tool access

Agents interact with Connapse through the MCP endpoint (POST /mcp). All 11 MCP tools documented in the Model Context Protocol section are available to agents.

What agents can do

  • Create, list, and delete containers (via MCP)
  • Upload and delete files, subject to connector write guards (via MCP)
  • Search across any container (via MCP)
  • List files and retrieve document content (via MCP)

What agents cannot do

  • Access any REST API endpoint (returns 403)
  • Manage users or roles
  • Change system settings (embedding, search, LLM configuration)
  • Create or manage other agents
  • Access the web UI

Security note: Since agents have system-wide container access via MCP, treat agent API keys with the same care as admin credentials. Revoke unused keys promptly.


Containers API

All container endpoints require authentication. RBAC rules:

  • GET endpoints require Viewer role minimum
  • POST, DELETE, reindex require Editor role minimum
  • Settings endpoints require Admin role

Create Container

Endpoint: POST /api/containers

Request Body:

{
  "name": "my-project",
  "description": "Project knowledge base",
  "connectorType": "MinIO",
  "connectorConfig": null
}

Fields:

  • name (required): lowercase alphanumeric + hyphens, 2-128 chars, globally unique
  • description (optional): Container description
  • connectorType (optional, default: MinIO): MinIO (Managed Storage — MinIO by default, overridable per deployment) | Filesystem | S3 | AzureBlob
  • connectorConfig (conditional): JSON string with connector-specific config

Connector Config Requirements:

Connector Required Fields Example
MinIO None (global config)
Filesystem rootPath {"rootPath":"C:\\docs"}
S3 bucketName, region {"bucketName":"docs","region":"us-east-1"}
AzureBlob storageAccountName, containerName {"storageAccountName":"acct","containerName":"docs"}

Response (201 Created):

{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "name": "my-project",
  "description": "Project knowledge base",
  "connectorType": "MinIO",
  "documentCount": 0,
  "createdAt": "2026-02-26T10:00:00Z",
  "updatedAt": "2026-02-26T10:00:00Z"
}

List Containers

Endpoint: GET /api/containers?skip=0&take=50

Query Parameters: skip, take (see Pagination)

Response (200 OK):

{
  "items": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "name": "my-project",
      "description": "Project knowledge base",
      "connectorType": "MinIO",
      "documentCount": 42,
      "createdAt": "2026-02-26T10:00:00Z",
      "updatedAt": "2026-02-26T10:00:00Z"
    }
  ],
  "totalCount": 1,
  "hasMore": false
}

Get Container

Endpoint: GET /api/containers/{id}

Response (200 OK | 404 Not Found)


Delete Container

Endpoint: DELETE /api/containers/{id}

Notes: Fails with 400 if the container still has files or folders. Must be empty first.

Response (204 No Content | 400 Bad Request)


Get Container Stats

Endpoint: GET /api/containers/{id}/stats

Auth: Viewer minimum

Response (200 OK):

{
  "containerId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "containerName": "my-project",
  "connectorType": "MinIO",
  "documents": {
    "total": 42,
    "ready": 40,
    "processing": 1,
    "failed": 1
  },
  "totalChunks": 1200,
  "totalSizeBytes": 52428800,
  "embeddingModels": [
    { "modelId": "nomic-embed-text", "dimensions": 768, "vectorCount": 1200 }
  ],
  "lastIndexedAt": "2026-03-09T10:00:00Z",
  "createdAt": "2026-02-26T10:00:00Z"
}

Container Files API

Upload Files

Upload one or more files into a container.

Endpoint: POST /api/containers/{id}/files

Content-Type: multipart/form-data

Form Fields:

  • files (required): One or more file parts
  • path (optional): Destination folder path (e.g., /docs/2026/)
  • strategy (optional): Chunking strategy (Semantic | FixedSize | Recursive, default: Semantic)

Response (200 OK):

{
  "documents": [
    {
      "documentId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "fileName": "report.pdf",
      "fileSize": 245678,
      "contentType": "application/pdf",
      "status": "Pending",
      "error": null
    }
  ],
  "successCount": 1,
  "failureCount": 0
}

Notes:

  • Files stream directly to MinIO (not buffered in memory)
  • Ingestion is asynchronous — track progress via SignalR or poll the file endpoint
  • Duplicate filenames in the same folder auto-increment: file (1).pdf, file (2).pdf
  • Write guard: S3 and AzureBlob containers block uploads (read-only). Filesystem containers respect the allowUpload flag. Returns 400 with { "error": "write_denied" } when blocked. See connectors.md — Write Guards.

List Files

Endpoint: GET /api/containers/{id}/files?skip=0&take=50

Query Parameters:

  • skip, take (required): See Pagination
  • path (optional): Browse a specific folder (e.g., ?path=/docs/)

Response (200 OK):

{
  "items": [
    {
      "type": "file",
      "documentId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "fileName": "report.pdf",
      "path": "/docs/report.pdf",
      "contentType": "application/pdf",
      "sizeBytes": 245678,
      "status": "Ready",
      "createdAt": "2026-02-26T10:00:00Z"
    }
  ],
  "totalCount": 1,
  "hasMore": false
}

Get File

Endpoint: GET /api/containers/{id}/files/{fileId}

Returns file metadata including current indexing status (Pending, Processing, Ready, Failed).


Get File Content

Endpoint: GET /api/containers/{id}/files/{fileId}/content

Auth: Viewer minimum

Returns the full text content of a file. For text files, the original content is returned. For binary formats (PDF, DOCX, PPTX), the extracted text is returned.

Content Negotiation:

  • Accept: text/plain — returns raw text content only
  • Accept: application/json (default) — returns structured response with metadata

Response (200 OK, JSON):

{
  "documentId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "fileName": "report.pdf",
  "path": "/docs/report.pdf",
  "contentType": "application/pdf",
  "sizeBytes": 245678,
  "createdAt": "2026-02-26T10:00:00Z",
  "content": "Machine learning is a subset of artificial intelligence..."
}

Errors:

  • 400 document_not_ready — file is still being ingested
  • 400 document_failed — file failed ingestion
  • 400 no_parser — no parser available for the file type
  • 404 — file or container not found

Check Reindex Status

Endpoint: GET /api/containers/{id}/files/{fileId}/reindex-check

Returns whether the file needs reindexing and the reason.


Delete File

Endpoint: DELETE /api/containers/{id}/files/{fileId}

Cascade deletes chunks, vectors, and removes the file from MinIO.

Write guard: S3 and AzureBlob containers block deletes. Filesystem containers respect the allowDelete flag. Returns 400 with { "error": "write_denied" } when blocked. See connectors.md — Write Guards.

Response (204 No Content)


Container Folders API

Create Folder

Endpoint: POST /api/containers/{id}/folders

Request Body:

{ "path": "/docs/2026/" }

Write guard: S3 and AzureBlob containers block folder creation. Filesystem containers respect the allowCreateFolder flag. Returns 400 with { "error": "write_denied" } when blocked.

Response (200 OK): Returns Folder object.


Delete Folder

Endpoint: DELETE /api/containers/{id}/folders?path=/docs/2026/

Cascade deletes all nested files, subfolders, chunks, vectors, and MinIO objects.

Write guard: S3 and AzureBlob containers block folder deletion. Filesystem containers respect the allowDelete flag. Returns 400 with { "error": "write_denied" } when blocked.

Response (204 No Content)


Container Search API

Search (GET)

Endpoint: GET /api/containers/{id}/search

Query Parameters:

  • q (required): Search query
  • mode (default: Hybrid): Semantic | Keyword | Hybrid
  • topK (default: 10): Number of results (max: 100)
  • minScore (optional): Minimum similarity score 0.0-1.0 (default: from settings, typically 0.5)
  • path (optional): Restrict search to a folder subtree

Response (200 OK):

{
  "hits": [
    {
      "chunkId": "7f8e9d1c-2b3a-4c5d-8e9f-1a2b3c4d5e6f",
      "documentId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "content": "Machine learning is a subset of artificial intelligence...",
      "score": 0.92,
      "metadata": {
        "fileName": "report.pdf",
        "chunkIndex": "5",
        "pageNumber": "12"
      }
    }
  ],
  "totalMatches": 1,
  "durationMs": 87
}

Search (POST)

Endpoint: POST /api/containers/{id}/search

Request Body:

{
  "query": "machine learning algorithms",
  "mode": "Hybrid",
  "topK": 20,
  "minScore": 0.6,
  "path": "/docs/",
  "filters": {
    "documentType": "pdf"
  }
}

Response: Same as GET search.


Container Reindex API

Reindex Container

Endpoint: POST /api/containers/{id}/reindex

Request Body (optional):

{
  "force": false,
  "detectSettingsChanges": true,
  "documentIds": null
}

Fields:

  • force (default: false): Re-process all files even if content hash unchanged
  • detectSettingsChanges (default: true): Force reindex if embedding/chunking settings changed
  • documentIds (optional): Reindex specific files only

Response (202 Accepted):

{
  "batchId": "9d3e7c1a-4b2f-4e8d-9c5a-6f8e1b3d7c2a",
  "totalDocuments": 42,
  "enqueuedCount": 38,
  "skippedCount": 4,
  "status": "Pending"
}

Settings API

All settings endpoints require Admin role.

Get Settings

Endpoint: GET /api/settings/{category}

Categories: embedding | chunking | search | llm | upload | awssso | azuread

Response (200 OK) — Example for embedding:

{
  "provider": "Ollama",
  "baseUrl": "http://ollama:11434",
  "model": "nomic-embed-text",
  "dimensions": 768,
  "timeout": 30,
  "batchSize": 4
}

Update Settings

Endpoint: PUT /api/settings/{category}

Notes: Changes take effect immediately (live reload via IOptionsMonitor<T>). No restart required.

Response (200 OK):

{
  "message": "Settings updated successfully",
  "category": "chunking",
  "updatedAt": "2026-02-26T11:45:00Z"
}

Test Connection

Endpoint: POST /api/settings/test-connection

Categories: Embedding | Llm | AwsSso | AzureAd | CrossEncoder

Request Body:

{
  "category": "Embedding",
  "settings": {
    "provider": "Ollama",
    "baseUrl": "http://localhost:11434",
    "model": "nomic-embed-text"
  },
  "timeoutSeconds": 10
}

Response (200 OK):

{
  "success": true,
  "message": "Connected to Ollama (3 models available)",
  "details": { "modelCount": 3 },
  "duration": "00:00:00.4530000"
}

Batches API

Get Batch Status

Endpoint: GET /api/batches/{id}/status

Auth: Viewer minimum

Response (200 OK): Ingestion progress for all jobs in the batch.


SignalR Hub (Real-Time)

Hub URL: /hubs/ingestion

Auth: Required — pass JWT via ?access_token=<token> query string, or use cookie session.

Subscribe to Job Progress

const connection = new signalR.HubConnectionBuilder()
  .withUrl("/hubs/ingestion?access_token=eyJ...")
  .build();

// Subscribe
await connection.invoke("SubscribeToJob", "job-id");

// Listen for updates
connection.on("IngestionProgress", (update) => {
  // update: { jobId, state, currentPhase, percentComplete, errorMessage, startedAt, completedAt }
  console.log(`${update.currentPhase}: ${update.percentComplete}%`);
});

await connection.start();

States: Pending | Processing | Completed | Failed

Phases: Parsing | Chunking | Embedding | Storing | Complete


Model Context Protocol (MCP)

Connapse exposes an MCP server for AI agent integration.

Endpoint: POST /mcp

Auth: Requires a valid Agent API key via X-Api-Key: cnp_<token> header.

Tool list: GET /mcp/tools

Available Tools (11)

Tool Required Parameters Optional Parameters Description
container_create name description Create a new container for organizing files
container_list List all containers with document counts
container_delete containerId Delete a container (must be empty for MinIO)
container_stats containerId Get statistics: document counts by status, chunk count, storage size, embedding model, last indexed time
upload_file containerId, fileName, + content or textContent path, strategy Upload a single file (base64 or raw text)
bulk_upload containerId, files (JSON array) Upload up to 100 files in one operation
list_files containerId path List files and folders at a given path
get_document containerId, fileId Retrieve full parsed text content by document ID or path
delete_file containerId, fileId Delete a file and its associated chunks and vectors
bulk_delete containerId, fileIds (JSON array) Delete up to 100 files in one operation
search_knowledge query, containerId mode, topK, path, minScore Semantic, keyword, or hybrid search within a container

Notes:

  • containerId accepts either a container GUID or container name (resolved automatically).
  • upload_file accepts either content (base64) for binary files or textContent (raw text) for text files — provide one, not both.
  • bulk_upload files is a JSON array of objects: {"filename":"name.txt", "content":"...", "encoding":"text|base64", "folderPath":"/optional/"}.
  • bulk_delete fileIds is a JSON array of document ID strings: ["id1","id2"].
  • get_document fileId accepts either a document UUID or a virtual path (e.g., /docs/readme.md).

Write Guards

Write operations (upload_file, bulk_upload, delete_file, bulk_delete) are subject to container write guards:

Connector Type Upload Delete Notes
Managed Storage Allowed Allowed Default connector (MinIO wire value); full read/write
InMemory Allowed Allowed Ephemeral storage
Filesystem Configurable Configurable Per-container allowUpload/allowDelete flags (default: allowed)
S3 Blocked Blocked Read-only; files are synced from the source bucket
AzureBlob Blocked Blocked Read-only; files are synced from the source container

When a write is blocked, the tool returns an error message explaining why (e.g., "S3 containers are read-only. Files are synced from the source.").

bulk_upload

Upload up to 100 files in a single operation. Each file is written to storage and queued for ingestion (parsing, chunking, embedding).

Parameters:

  • containerId (required): Container ID (UUID) or name
  • files (required): JSON array of file objects (max 100)

File object schema:

{
  "filename": "report.pdf",
  "content": "base64-encoded-content-here",
  "encoding": "base64",
  "folderPath": "/docs/"
}
Field Required Description
filename Yes Target filename
content Yes File content (raw text or base64-encoded)
encoding No "text" (default) or "base64" for binary files
folderPath No Destination folder path (default: "/")

Success response:

Uploaded 3 of 3 file(s) to container 'my-project'.

All files queued for ingestion (parsing, chunking, embedding).

Partial failure response:

Uploaded 2 of 3 file(s) to container 'my-project'.

Failures:
- report.pdf: invalid base64 content

Errors:

Error Cause
'files' must be a valid JSON array Malformed JSON
'files' array must not be empty Empty array
Maximum 100 files per bulk_upload call Too many files
Container '{id}' not found Invalid container ID/name
missing 'filename' File object missing filename
missing 'content' File object missing content
invalid base64 content Bad base64 when encoding is "base64"

Notes:

  • All files share a single batch ID for tracking
  • Uses Semantic chunking strategy
  • Intermediate folders are created automatically
  • Subject to write guards

bulk_delete

Delete up to 100 files from a container in a single operation. Removes database records and backing storage files.

Parameters:

  • containerId (required): Container ID (UUID) or name
  • fileIds (required): JSON array of document ID strings (max 100)

Example input:

["3fa85f64-5717-4562-b3fc-2c963f66afa6", "7f8e9d1c-2b3a-4c5d-8e9f-1a2b3c4d5e6f"]

Success response:

Deleted 2 of 2 file(s).

Partial failure response:

Deleted 1 of 2 file(s).

Warnings (1):
- 7f8e9d1c (...): storage cleanup failed

Failures:
- abc123: not found

Errors:

Error Cause
'fileIds' must be a valid JSON array of strings Malformed JSON
'fileIds' array must not be empty Empty array
Maximum 100 files per bulk_delete call Too many files
Container '{id}' not found Invalid container ID/name

Notes:

  • Files not found or belonging to a different container are reported as failures
  • Storage deletion failures are non-fatal warnings (DB record is still removed)
  • Does not clean up empty parent folders
  • Subject to write guards

CLI

The connapse command-line client lives in its own repository: Destrayon/connapse-cli. Install via:

dotnet tool install -g Connapse.CLI
# or: download a binary from https://github.com/Destrayon/connapse-cli/releases/latest

See the connapse-cli README for the full command reference and authentication flow.

connapse auth login --server https://your-server
connapse --help

Error Codes

All API errors follow RFC 7807 Problem Details format.

Status Description
400 Invalid request parameters or body
401 Missing or invalid authentication
403 Insufficient role/permissions
404 Resource not found
409 Conflict (duplicate name, already revoked, etc.)
413 File exceeds UploadSettings.MaxFileSizeMb
415 File type not in UploadSettings.AllowedExtensions
429 Rate limit exceeded (see rate limiting)
500 Unexpected server error
503 External service (Ollama, MinIO) unreachable

Container Connector Endpoints (v0.3.0)

Test Connector Connection

Test a cloud connector configuration before creating a container.

Endpoint: POST /api/containers/test-connection

Request Body:

{
  "connectorType": "S3",
  "connectorConfig": "{\"bucketName\":\"docs\",\"region\":\"us-east-1\"}",
  "timeoutSeconds": 15
}

Response (200 OK):

{
  "success": true,
  "message": "Connected successfully",
  "details": { "bucketName": "docs", "region": "us-east-1", "objectsFound": 3 },
  "elapsed": "00:00:01.234"
}

Supported connectors: S3, AzureBlob, Managed Storage (wire value: MinIO).


Sync Container

Trigger an on-demand sync for cloud containers.

Endpoint: POST /api/containers/{id}/sync

Notes:

  • Returns 400 for Filesystem ("live watch is enough")
  • Returns 404 for non-existent containers
  • Cloud scope enforcement: user must have a linked identity for the container's cloud provider

Response (200 OK):

{
  "batchId": "abc123",
  "totalFiles": 42,
  "enqueuedCount": 5,
  "skippedCount": 37
}

Container Settings Endpoints (v0.3.0)

Get Container Settings

Endpoint: GET /api/containers/{id}/settings

Returns per-container settings overrides. Null values mean "use global setting".

Response (200 OK):

{
  "chunking": null,
  "embedding": { "provider": "OpenAI", "model": "text-embedding-3-small", "dimensions": 1536 },
  "search": null,
  "upload": null
}

Save Container Settings

Endpoint: PUT /api/containers/{id}/settings

Request Body:

{
  "embedding": { "provider": "OpenAI", "model": "text-embedding-3-small", "dimensions": 1536 }
}

Null or omitted categories are cleared (reset to global).

Response (200 OK)


Embedding Model Endpoints (v0.3.0)

Get Embedding Models

Discover which embedding models have vectors in the database.

Endpoint: GET /api/settings/embedding-models

Response (200 OK):

{
  "currentModel": "nomic-embed-text",
  "models": [
    { "modelId": "nomic-embed-text", "dimensions": 768, "vectorCount": 1200 },
    { "modelId": "text-embedding-3-small", "dimensions": 1536, "vectorCount": 50 }
  ]
}

Get Container Embedding Models

Endpoint: GET /api/containers/{id}/search/models

Same response as above, but scoped to a specific container.


Trigger Reindex

Endpoint: POST /api/settings/reindex

Fire-and-forget reindex with settings change detection.

Response (202 Accepted)


Get Reindex Status

Endpoint: GET /api/settings/reindex/status

Response (200 OK):

{
  "queueDepth": 12,
  "isActive": true
}

Cloud Identity Endpoints (v0.3.0)

Base path: /api/v1/auth/cloud

All endpoints require authentication.

Start AWS Device Authorization

Endpoint: POST /api/v1/auth/cloud/aws/device-auth

Returns a user code and verification URL for the IAM Identity Center device auth flow.

Response (200 OK):

{
  "userCode": "ABCD-EFGH",
  "verificationUri": "https://device.sso.us-east-1.amazonaws.com/",
  "verificationUriComplete": "https://device.sso.us-east-1.amazonaws.com/?user_code=ABCD-EFGH",
  "deviceCode": "...",
  "expiresInSeconds": 600,
  "intervalSeconds": 5
}

Error (400): aws_sso_not_configured if admin hasn't set Issuer URL + Region.


Poll AWS Device Authorization

Endpoint: POST /api/v1/auth/cloud/aws/device-auth/poll

Request Body:

{ "deviceCode": "..." }

Response (200 OK — pending):

{ "status": "pending" }

Response (200 OK — complete):

{
  "status": "complete",
  "identity": {
    "id": "...",
    "provider": "AWS",
    "data": { "principalArn": "123456789012", "accountId": "123456789012", "displayName": "My Account" },
    "createdAt": "...",
    "lastUsedAt": null
  }
}

Get Azure Connect URL

Endpoint: GET /api/v1/auth/cloud/azure/connect

Redirects to Azure AD authorize endpoint with PKCE challenge. Sets __connapse_az_state and __connapse_az_pkce cookies (10-min TTL).

Response: 302 Redirect to Azure AD.


Azure Callback

Endpoint: GET /api/v1/auth/cloud/azure/callback

Handles the OAuth2 callback from Azure AD. Validates state, exchanges code for ID token, stores identity.

Response: 302 Redirect to /profile.


List Cloud Identities

Endpoint: GET /api/v1/auth/cloud

Response (200 OK): Array of linked cloud identities.


Disconnect Cloud Identity

Endpoint: DELETE /api/v1/auth/cloud/{provider}

Path Parameters: provider = AWS | Azure

Removes the linked identity and evicts cached scope entries.

Response (204 No Content | 404 Not Found)


Versioning

Current Version: v0.3.2

Auth endpoints are under /api/v1/auth/ and /api/v1/agents/. Container endpoints remain under /api/containers/. Cloud identity endpoints are under /api/v1/auth/cloud/.


References