Knowledge Roles API

Manage role-based access control (RBAC) for knowledge items. These endpoints allow you to assign and unassign roles to specific knowledge items, controlling which users can access each piece of content based on their assigned roles.

Prerequisites

Before using these endpoints, ensure that:

  1. RBAC is enabled for your workspace (see Roles API)
  2. Roles have been created in your workspace
  3. You have your workspace API key

Available Endpoints

List Roles for Knowledge

GET /v1/workspaces/{workspaceId}/knowledge/{knowledgeId}/role

Get all roles assigned to a specific knowledge item.

Assign Roles to Knowledge

POST /v1/workspaces/{workspaceId}/knowledge/{knowledgeId}/role

Assign multiple roles to a knowledge item.

Unassign Roles from Knowledge

DELETE /v1/workspaces/{workspaceId}/knowledge/{knowledgeId}/role

Remove role assignments from a knowledge item.


List Roles

Get all roles currently assigned to a specific knowledge item.

Endpoint

GET /v1/workspaces/{workspaceId}/knowledge/{knowledgeId}/role

Authentication

Requires Bearer token authentication. See Authentication for details.

Authorization: Bearer YOUR_ACCESS_TOKEN

Path Parameters

ParameterTypeRequiredDescription
workspaceIdstring (UUID)YesThe ID of your workspace
knowledgeIdstring (UUID)YesThe ID of the knowledge item

Response

Success Response

Status Code: 200 OK

Headers:

X-API-Version: v1

Body:

[
  {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "Sales Team",
    "description": "Access for sales team members",
    "metadata": {
      "department": "sales",
      "level": "standard"
    }
  },
  {
    "id": "789e0123-f45a-67b8-c901-234567890def",
    "name": "Support Team",
    "description": "Access for customer support",
    "metadata": {
      "department": "support",
      "level": "premium"
    }
  }
]

Response Fields

FieldTypeDescription
idstring (UUID)Unique identifier for the role
namestringRole name
descriptionstringRole description
metadataobjectCustom metadata associated with the role

Example

curl -X GET \
  'https://api.sharely.ai/v1/workspaces/your-workspace-id/knowledge/550e8400-e29b-41d4-a716-446655440000/role' \
  -H 'x-api-key: sk-sharely-your-api-key'

Response:

[
  {
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "name": "Sales Team",
    "description": "Sales team role",
    "metadata": {}
  }
]

Assign Roles

Assign multiple roles to a knowledge item. This is an asynchronous operation that processes role assignments in the background.

Endpoint

POST /v1/workspaces/{workspaceId}/knowledge/{knowledgeId}/role

Authentication

Requires Bearer token authentication. See Authentication for details.

Authorization: Bearer YOUR_ACCESS_TOKEN

Path Parameters

ParameterTypeRequiredDescription
workspaceIdstring (UUID)YesThe ID of your workspace
knowledgeIdstring (UUID)YesThe ID of the knowledge item

Headers

HeaderTypeRequiredDescription
organizationIdstring (UUID)YesYour organization ID
x-api-keystringYesYour workspace API key
Content-TypestringYesMust be application/json

Request Body

FieldTypeRequiredDescription
roleIdsarray of string (UUID)YesArray of role IDs to assign to this knowledge item

Response

Success Response

Status Code: 200 OK

Headers:

X-API-Version: v1

Body:

{
  "workspaceId": "your-workspace-id",
  "knowledgeId": "550e8400-e29b-41d4-a716-446655440000",
  "organizationId": "your-organization-id",
  "roleIds": [
    "123e4567-e89b-12d3-a456-426614174000",
    "789e0123-f45a-67b8-c901-234567890def"
  ]
}

Notes

Asynchronous Processing

Role assignment is an asynchronous operation. The API returns immediately and processes the assignments in the background using a Temporal workflow. A background job is created to track the operation.

Important: Currently, there is no v1 API endpoint to check the status of these async operations when using API key authentication. The workflow processes in the background and you can verify completion by:

  • Calling the List Roles endpoint to see if roles have been assigned
  • Implementing a polling mechanism to check role assignments
  • Using the user-authenticated endpoint GET /workspaces/{workspaceId}/role/status if you have user credentials (not recommended for API key workflows)

Recommendation: Treat these operations as eventually consistent. The role assignments typically complete within seconds, but may take longer for large batches.

Future Enhancement: The following v1 API endpoints are planned to support workflow status checking with API key authentication:

  • GET /v1/workspaces/{workspaceId}/workflows/{workflowId}/status - Check status of any workflow by ID
  • GET /v1/workspaces/{workspaceId}/background-jobs - List all background jobs for the workspace
  • GET /v1/workspaces/{workspaceId}/background-jobs/{jobId} - Get specific background job status

These endpoints will return workflow status information including:

  • status: Current workflow state (RUNNING, COMPLETED, FAILED, etc.)
  • progress: Percentage complete for long-running operations
  • result: Final result data when completed
  • error: Error details if the workflow failed

RBAC Requirements

  • RBAC must be enabled for your workspace (rbacStatus === ACTIVE)
  • The workspace must not be deleted
  • All role IDs must exist in the workspace

Example

curl -X POST \
  'https://api.sharely.ai/v1/workspaces/your-workspace-id/knowledge/550e8400-e29b-41d4-a716-446655440000/role' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
  -H 'organizationid: your-organization-id' \
  -H 'organizationId: your-organization-id' \
  -H 'Content-Type: application/json' \
  -d '{
    "roleIds": [
      "123e4567-e89b-12d3-a456-426614174000",
      "789e0123-f45a-67b8-c901-234567890def"
    ]
  }'

Response:

{
  "workspaceId": "your-workspace-id",
  "knowledgeId": "550e8400-e29b-41d4-a716-446655440000",
  "organizationId": "your-organization-id",
  "roleIds": [
    "123e4567-e89b-12d3-a456-426614174000",
    "789e0123-f45a-67b8-c901-234567890def"
  ]
}

Unassign Roles

Remove role assignments from a knowledge item. This is an asynchronous operation that processes role removal in the background.

Endpoint

DELETE /v1/workspaces/{workspaceId}/knowledge/{knowledgeId}/role

Authentication

Requires Bearer token authentication. See Authentication for details.

Authorization: Bearer YOUR_ACCESS_TOKEN

Path Parameters

ParameterTypeRequiredDescription
workspaceIdstring (UUID)YesThe ID of your workspace
knowledgeIdstring (UUID)YesThe ID of the knowledge item

Headers

HeaderTypeRequiredDescription
organizationIdstring (UUID)YesYour organization ID
x-api-keystringYesYour workspace API key
Content-TypestringYesMust be application/json

Request Body

FieldTypeRequiredDescription
roleIdsarray of string (UUID)YesArray of role IDs to remove from this knowledge item

Response

Success Response

Status Code: 200 OK

Headers:

X-API-Version: v1

Body:

{
  "workspaceId": "your-workspace-id",
  "knowledgeId": "550e8400-e29b-41d4-a716-446655440000",
  "organizationId": "your-organization-id",
  "roleIds": [
    "123e4567-e89b-12d3-a456-426614174000"
  ]
}

Notes

Asynchronous Processing

Role unassignment is an asynchronous operation. The API returns immediately and processes the removals in the background using a Temporal workflow.

Status Checking: See the note in the Assign Roles section about checking async operation status. The same limitations and recommendations apply.

RBAC Requirements

  • RBAC must be enabled for your workspace
  • The workspace must not be deleted
  • Removing a role makes the knowledge item inaccessible to users with only that role

Example

curl -X DELETE \
  'https://api.sharely.ai/v1/workspaces/your-workspace-id/knowledge/550e8400-e29b-41d4-a716-446655440000/role' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
  -H 'organizationid: your-organization-id' \
  -H 'organizationId: your-organization-id' \
  -H 'Content-Type: application/json' \
  -d '{
    "roleIds": [
      "123e4567-e89b-12d3-a456-426614174000"
    ]
  }'

Response:

{
  "workspaceId": "your-workspace-id",
  "knowledgeId": "550e8400-e29b-41d4-a716-446655440000",
  "organizationId": "your-organization-id",
  "roleIds": [
    "123e4567-e89b-12d3-a456-426614174000"
  ]
}

Error Responses

400 Bad Request

Invalid request parameters:

{
  "error": "Bad Request",
  "message": "roleIds must be an array of valid UUIDs"
}

401 Unauthorized

Invalid or missing API key:

{
  "error": "Unauthorized",
  "message": "Invalid or missing API key"
}

403 Forbidden

RBAC not enabled:

{
  "error": "Forbidden",
  "message": "RBAC is not enabled for this workspace"
}

404 Not Found

Workspace, knowledge item, or role not found:

{
  "error": "Not Found",
  "message": "Workspace not found"
}
{
  "error": "Not Found",
  "message": "Knowledge item not found"
}
{
  "error": "Not Found",
  "message": "One or more roles not found"
}

410 Gone

Workspace deleted:

{
  "error": "Gone",
  "message": "Workspace is deleted"
}

500 Internal Server Error

Server error during processing:

{
  "error": "Internal Server Error",
  "message": "Failed to process role assignment"
}

Common Use Cases

Restrict Knowledge to Specific Teams

Assign knowledge items to specific team roles to control access:

const API_KEY = 'sk-sharely-your-api-key';
const WORKSPACE_ID = 'your-workspace-id';
const ORGANIZATION_ID = 'your-organization-id';
const BASE_URL = 'https://api.sharely.ai';
 
async function restrictKnowledgeToTeams(knowledgeId, roleIds) {
  const response = await fetch(
    `${BASE_URL}/v1/workspaces/${WORKSPACE_ID}/knowledge/${knowledgeId}/role`,
    {
      method: 'POST',
      headers: {
        'x-api-key': API_KEY,
        'organizationId': ORGANIZATION_ID,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ roleIds })
    }
  );
 
  if (!response.ok) {
    throw new Error(`Failed to assign roles: ${response.statusText}`);
  }
 
  return await response.json();
}
 
// Restrict sales documentation to sales and management teams
const salesDocId = '550e8400-e29b-41d4-a716-446655440000';
const salesRoleId = '123e4567-e89b-12d3-a456-426614174000';
const managementRoleId = '789e0123-f45a-67b8-c901-234567890def';
 
await restrictKnowledgeToTeams(salesDocId, [salesRoleId, managementRoleId]);
console.log('Knowledge restricted to sales and management teams');

Audit Knowledge Access

Check which roles have access to a knowledge item:

async function auditKnowledgeAccess(knowledgeId) {
  const response = await fetch(
    `${BASE_URL}/v1/workspaces/${WORKSPACE_ID}/knowledge/${knowledgeId}/role`,
    {
      method: 'GET',
      headers: {
        'x-api-key': API_KEY
      }
    }
  );
 
  if (!response.ok) {
    throw new Error(`Failed to fetch roles: ${response.statusText}`);
  }
 
  const roles = await response.json();
 
  console.log(`Knowledge item ${knowledgeId} is accessible to:`);
  roles.forEach(role => {
    console.log(`- ${role.name} (${role.id})`);
  });
 
  return roles;
}
 
await auditKnowledgeAccess('550e8400-e29b-41d4-a716-446655440000');

Bulk Role Assignment

Assign the same roles to multiple knowledge items:

async function bulkAssignRoles(knowledgeIds, roleIds) {
  const results = [];
 
  for (const knowledgeId of knowledgeIds) {
    try {
      const result = await restrictKnowledgeToTeams(knowledgeId, roleIds);
      results.push({
        knowledgeId,
        status: 'success',
        data: result
      });
    } catch (error) {
      results.push({
        knowledgeId,
        status: 'error',
        error: error.message
      });
    }
 
    // Rate limiting
    await new Promise(resolve => setTimeout(resolve, 100));
  }
 
  return results;
}
 
// Assign sales and support roles to multiple knowledge items
const knowledgeIds = [
  '550e8400-e29b-41d4-a716-446655440000',
  '789e0123-f45a-67b8-c901-234567890def',
  '456e7890-a12b-34c5-d678-901234567890'
];
 
const roleIds = [
  '123e4567-e89b-12d3-a456-426614174000', // Sales
  '789e0123-f45a-67b8-c901-234567890def'  // Support
];
 
const results = await bulkAssignRoles(knowledgeIds, roleIds);
console.log(`Successfully assigned: ${results.filter(r => r.status === 'success').length}`);
console.log(`Failed: ${results.filter(r => r.status === 'error').length}`);

Update Knowledge Permissions

Replace existing role assignments with new ones:

async function updateKnowledgePermissions(knowledgeId, newRoleIds) {
  // Step 1: Get current roles
  const currentRoles = await fetch(
    `${BASE_URL}/v1/workspaces/${WORKSPACE_ID}/knowledge/${knowledgeId}/role`,
    {
      method: 'GET',
      headers: { 'x-api-key': API_KEY }
    }
  ).then(r => r.json());
 
  // Step 2: Remove all current roles
  if (currentRoles.length > 0) {
    const currentRoleIds = currentRoles.map(r => r.id);
    await fetch(
      `${BASE_URL}/v1/workspaces/${WORKSPACE_ID}/knowledge/${knowledgeId}/role`,
      {
        method: 'DELETE',
        headers: {
          'x-api-key': API_KEY,
          'organizationId': ORGANIZATION_ID,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({ roleIds: currentRoleIds })
      }
    );
  }
 
  // Step 3: Assign new roles
  await fetch(
    `${BASE_URL}/v1/workspaces/${WORKSPACE_ID}/knowledge/${knowledgeId}/role`,
    {
      method: 'POST',
      headers: {
        'x-api-key': API_KEY,
        'organizationId': ORGANIZATION_ID,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ roleIds: newRoleIds })
    }
  );
 
  console.log(`Updated permissions for knowledge ${knowledgeId}`);
}
 
// Change from sales-only to sales and management
await updateKnowledgePermissions(
  '550e8400-e29b-41d4-a716-446655440000',
  ['123e4567-e89b-12d3-a456-426614174000', '789e0123-f45a-67b8-c901-234567890def']
);

Python Example

import requests
from typing import List
 
API_KEY = 'sk-sharely-your-api-key'
WORKSPACE_ID = 'your-workspace-id'
ORGANIZATION_ID = 'your-organization-id'
BASE_URL = 'https://api.sharely.ai'
 
def assign_roles_to_knowledge(knowledge_id: str, role_ids: List[str]):
    """Assign multiple roles to a knowledge item"""
    response = requests.post(
        f'{BASE_URL}/v1/workspaces/{WORKSPACE_ID}/knowledge/{knowledge_id}/role',
        headers={
            'x-api-key': API_KEY,
            'organizationId': ORGANIZATION_ID,
            'Content-Type': 'application/json'
        },
        json={'roleIds': role_ids}
    )
    response.raise_for_status()
    return response.json()
 
def get_knowledge_roles(knowledge_id: str):
    """Get all roles assigned to a knowledge item"""
    response = requests.get(
        f'{BASE_URL}/v1/workspaces/{WORKSPACE_ID}/knowledge/{knowledge_id}/role',
        headers={'x-api-key': API_KEY}
    )
    response.raise_for_status()
    return response.json()
 
def remove_roles_from_knowledge(knowledge_id: str, role_ids: List[str]):
    """Remove role assignments from a knowledge item"""
    response = requests.delete(
        f'{BASE_URL}/v1/workspaces/{WORKSPACE_ID}/knowledge/{knowledge_id}/role',
        headers={
            'x-api-key': API_KEY,
            'organizationId': ORGANIZATION_ID,
            'Content-Type': 'application/json'
        },
        json={'roleIds': role_ids}
    )
    response.raise_for_status()
    return response.json()
 
# Usage
knowledge_id = '550e8400-e29b-41d4-a716-446655440000'
sales_role_id = '123e4567-e89b-12d3-a456-426614174000'
support_role_id = '789e0123-f45a-67b8-c901-234567890def'
 
# Assign roles
result = assign_roles_to_knowledge(knowledge_id, [sales_role_id, support_role_id])
print(f"Assigned roles: {result}")
 
# List current roles
roles = get_knowledge_roles(knowledge_id)
print(f"Current roles: {[role['name'] for role in roles]}")
 
# Remove a role
remove_roles_from_knowledge(knowledge_id, [support_role_id])
print("Removed support role")

Best Practices

Role Validation

Always verify that roles exist before assigning them:

async function validateAndAssignRoles(knowledgeId, roleIds) {
  // Validate each role exists
  for (const roleId of roleIds) {
    try {
      const response = await fetch(
        `${BASE_URL}/v1/workspaces/${WORKSPACE_ID}/role/${roleId}`,
        {
          headers: { 'x-api-key': API_KEY }
        }
      );
 
      if (!response.ok) {
        throw new Error(`Role ${roleId} not found`);
      }
    } catch (error) {
      console.error(`Validation failed: ${error.message}`);
      return null;
    }
  }
 
  // All roles valid, proceed with assignment
  return await restrictKnowledgeToTeams(knowledgeId, roleIds);
}

Error Handling

Handle asynchronous processing errors gracefully:

async function safeAssignRoles(knowledgeId, roleIds) {
  try {
    const result = await fetch(
      `${BASE_URL}/v1/workspaces/${WORKSPACE_ID}/knowledge/${knowledgeId}/role`,
      {
        method: 'POST',
        headers: {
          'x-api-key': API_KEY,
          'organizationId': ORGANIZATION_ID,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({ roleIds })
      }
    );
 
    if (!result.ok) {
      const error = await result.json();
      console.error('Assignment failed:', error);
 
      // Handle specific errors
      if (error.message?.includes('RBAC is not enabled')) {
        console.error('Please enable RBAC for your workspace first');
      }
 
      return null;
    }
 
    return await result.json();
  } catch (error) {
    console.error('Network error:', error);
    return null;
  }
}

Rate Limiting

When processing multiple knowledge items, implement rate limiting:

async function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}
 
async function bulkAssignWithRateLimit(assignments, requestsPerSecond = 5) {
  const delayMs = 1000 / requestsPerSecond;
  const results = [];
 
  for (const { knowledgeId, roleIds } of assignments) {
    const result = await safeAssignRoles(knowledgeId, roleIds);
    results.push({ knowledgeId, result });
 
    // Wait before next request
    await sleep(delayMs);
  }
 
  return results;
}

Verifying Async Completion

Since there's no direct status endpoint for API key authenticated operations, implement polling to verify completion:

async function waitForRoleAssignment(knowledgeId, expectedRoleIds, maxWaitMs = 30000) {
  const startTime = Date.now();
  const pollInterval = 1000; // Check every second
 
  while (Date.now() - startTime < maxWaitMs) {
    // Get current roles
    const roles = await fetch(
      `${BASE_URL}/v1/workspaces/${WORKSPACE_ID}/knowledge/${knowledgeId}/role`,
      {
        method: 'GET',
        headers: { 'x-api-key': API_KEY }
      }
    ).then(r => r.json());
 
    // Check if all expected roles are present
    const currentRoleIds = roles.map(r => r.id);
    const allPresent = expectedRoleIds.every(id => currentRoleIds.includes(id));
 
    if (allPresent) {
      console.log('Role assignment completed');
      return true;
    }
 
    // Wait before next check
    await new Promise(resolve => setTimeout(resolve, pollInterval));
  }
 
  throw new Error('Timeout waiting for role assignment');
}
 
// Usage
await restrictKnowledgeToTeams(knowledgeId, [roleId1, roleId2]);
await waitForRoleAssignment(knowledgeId, [roleId1, roleId2]);
console.log('Roles successfully assigned and verified');

Idempotency

Assignment operations are idempotent - assigning the same role multiple times has the same effect as assigning it once:

// Safe to call multiple times
await restrictKnowledgeToTeams(knowledgeId, [roleId]);
await restrictKnowledgeToTeams(knowledgeId, [roleId]); // No error, no duplicate

Integration with Other APIs

Create Knowledge and Assign Roles

async function createRestrictedKnowledge(content, roleIds) {
  // Step 1: Create knowledge
  const createResponse = await fetch(
    `${BASE_URL}/v1/workspaces/${WORKSPACE_ID}/knowledge`,
    {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${ACCESS_TOKEN}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        type: 'STRING',
        content: content,
        title: 'Restricted Document'
      })
    }
  );
 
  const { id: knowledgeId } = await createResponse.json();
 
  // Step 2: Assign roles
  await restrictKnowledgeToTeams(knowledgeId, roleIds);
 
  return knowledgeId;
}

Sync Roles Across Knowledge Items

async function syncRolesAcrossKnowledge(sourceKnowledgeId, targetKnowledgeIds) {
  // Get roles from source
  const sourceRoles = await get_knowledge_roles(sourceKnowledgeId);
  const roleIds = sourceRoles.map(r => r.id);
 
  // Apply to all targets
  const results = await bulkAssignRoles(targetKnowledgeIds, roleIds);
 
  return results;
}

Related APIs

  • Roles API - Create and manage roles for your workspace
  • Knowledge API - Create and manage knowledge items
  • Spaces API - Provision user spaces with role-based access