Update Metadata

Update custom metadata fields for a knowledge item. This endpoint allows you to add, update, or remove custom metadata properties while keeping the content and reserved fields unchanged.

Endpoint

PUT /v1/workspaces/{workspaceId}/knowledge/{knowledgeId}/metadata

Authentication

Requires Bearer token authentication. See Authentication for details.

Path Parameters

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

Request Body

FieldTypeRequiredDescription
typestringYesKnowledge type: URL, FILE, LINK, STRING, WEBSITE, or ELASTICSEARCH_INDEX. Must match the item's actual type.
metadataobjectYesCustom metadata as key-value pairs. Values must be strings or numbers only.
removeMetadataKeysarray of stringsNoArray of metadata keys to remove

Metadata Value Constraints

Important: Metadata values can only be strings or numbers. Nested objects, arrays, booleans, or null values are not allowed.

// Valid metadata
{
  "metadata": {
    "department": "Engineering",
    "version": "2.0",
    "priority": 5,
    "reviewedBy": "John Doe"
  }
}
 
// Invalid metadata - will be rejected
{
  "metadata": {
    "settings": {"nested": "object"},  // ❌ No nested objects
    "tags": ["tag1", "tag2"],           // ❌ No arrays
    "active": true,                      // ❌ No booleans
    "deletedAt": null                    // ❌ No null values
  }
}

Reserved Field Restrictions

The following fields cannot be updated via this endpoint:

Attempting to update these fields will result in an error.

Response

Success Response

Status Code: 200 OK

Headers:

X-API-Version: v1

Body:

{
  "knowledgeId": "550e8400-e29b-41d4-a716-446655440000"
}

Examples

Add Custom Metadata

Add custom metadata fields to a knowledge item:

curl -X PUT \
  'https://api.sharely.ai/v1/workspaces/your-workspace-id/knowledge/123e4567-e89b-12d3-a456-426614174000/metadata' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "type": "FILE",
    "metadata": {
      "department": "Engineering",
      "version": "2.1",
      "reviewedBy": "Jane Doe",
      "priority": 3
    }
  }'

Response:

{
  "knowledgeId": "123e4567-e89b-12d3-a456-426614174000"
}

Update Existing Metadata

Update specific metadata fields while preserving others:

curl -X PUT \
  'https://api.sharely.ai/v1/workspaces/your-workspace-id/knowledge/123e4567-e89b-12d3-a456-426614174000/metadata' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "type": "FILE",
    "metadata": {
      "version": "2.2",
      "lastUpdated": "2025-01-16"
    }
  }'

Remove Metadata Fields

Remove specific metadata fields using removeMetadataKeys:

curl -X PUT \
  'https://api.sharely.ai/v1/workspaces/your-workspace-id/knowledge/123e4567-e89b-12d3-a456-426614174000/metadata' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "type": "FILE",
    "metadata": {},
    "removeMetadataKeys": ["oldField", "deprecatedField"]
  }'

Add and Remove Metadata Simultaneously

You can add new metadata and remove old fields in a single request:

curl -X PUT \
  'https://api.sharely.ai/v1/workspaces/your-workspace-id/knowledge/123e4567-e89b-12d3-a456-426614174000/metadata' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "type": "URL",
    "metadata": {
      "category": "Documentation",
      "updatedAt": "2025-01-16"
    },
    "removeMetadataKeys": ["oldCategory", "tempField"]
  }'

JavaScript Example

const API_KEY = 'YOUR_API_KEY';
const WORKSPACE_ID = 'your-workspace-id';
const BASE_URL = 'https://api.sharely.ai/v1';
 
async function updateMetadata(knowledgeId, type, metadata, removeKeys = null) {
  const body = {
    type: type,
    metadata: metadata
  };
 
  if (removeKeys && removeKeys.length > 0) {
    body.removeMetadataKeys = removeKeys;
  }
 
  const response = await fetch(
    `${BASE_URL}/workspaces/${WORKSPACE_ID}/knowledge/${knowledgeId}/metadata`,
    {
      method: 'PUT',
      headers: {
        'Authorization': `Bearer ${API_KEY}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(body)
    }
  );
 
  if (!response.ok) {
    throw new Error(`Update failed: ${response.statusText}`);
  }
 
  return await response.json();
}
 
// Usage - Add metadata
try {
  const result = await updateMetadata(
    '123e4567-e89b-12d3-a456-426614174000',
    'FILE',
    {
      department: 'Engineering',
      version: '2.1',
      priority: 5
    }
  );
  console.log('Metadata updated:', result.knowledgeId);
} catch (error) {
  console.error('Update failed:', error.message);
}
 
// Usage - Add and remove metadata
try {
  const result = await updateMetadata(
    '123e4567-e89b-12d3-a456-426614174000',
    'FILE',
    {
      newField: 'newValue',
      updatedAt: '2025-01-16'
    },
    ['oldField', 'deprecatedField']
  );
  console.log('Metadata updated:', result.knowledgeId);
} catch (error) {
  console.error('Update failed:', error.message);
}

Python Example

import requests
import json
 
API_KEY = 'YOUR_API_KEY'
WORKSPACE_ID = 'your-workspace-id'
BASE_URL = 'https://api.sharely.ai/v1'
 
def update_metadata(knowledge_id, knowledge_type, metadata, remove_keys=None):
    payload = {
        'type': knowledge_type,
        'metadata': metadata
    }
 
    if remove_keys:
        payload['removeMetadataKeys'] = remove_keys
 
    response = requests.put(
        f'{BASE_URL}/workspaces/{WORKSPACE_ID}/knowledge/{knowledge_id}/metadata',
        headers={
            'Authorization': f'Bearer {API_KEY}',
            'Content-Type': 'application/json'
        },
        json=payload
    )
 
    response.raise_for_status()
    return response.json()
 
# Usage - Add metadata
try:
    result = update_metadata(
        '123e4567-e89b-12d3-a456-426614174000',
        'FILE',
        {
            'department': 'Engineering',
            'version': '2.1',
            'priority': 5
        }
    )
    print(f"Metadata updated: {result['knowledgeId']}")
except requests.exceptions.HTTPError as error:
    print(f"Update failed: {error}")
 
# Usage - Add and remove metadata
try:
    result = update_metadata(
        '123e4567-e89b-12d3-a456-426614174000',
        'FILE',
        {
            'newField': 'newValue',
            'updatedAt': '2025-01-16'
        },
        ['oldField', 'deprecatedField']
    )
    print(f"Metadata updated: {result['knowledgeId']}")
except requests.exceptions.HTTPError as error:
    print(f"Update failed: {error}")

Error Responses

400 Bad Request

Missing required fields:

{
  "error": "Bad Request",
  "message": "Missing required field: metadata"
}

Invalid metadata values (nested objects):

{
  "error": "Bad Request",
  "message": "Metadata values must be strings or numbers only, nested objects are not allowed"
}

Attempting to update reserved fields:

{
  "error": "Bad Request",
  "message": "Title cannot be updated with this endpoint, use the reserved fields endpoint"
}
{
  "error": "Bad Request",
  "message": "Language cannot be updated with this endpoint, use the reserved fields endpoint"
}

401 Unauthorized

Invalid or missing API key:

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

403 Forbidden

Knowledge not in completed status:

{
  "error": "Forbidden",
  "message": "Knowledge with ID {knowledgeId} is not in completed status"
}

404 Not Found

Knowledge item doesn't exist:

{
  "error": "Not Found",
  "message": "Knowledge with ID {knowledgeId} not found"
}

422 Unprocessable Entity

Type mismatch:

{
  "error": "Unprocessable Entity",
  "message": "Type mismatch"
}

500 Internal Server Error

Server error during update:

{
  "error": "Internal Server Error",
  "message": "Failed to update metadata"
}

Use Cases

Tag Content by Department

Add organizational metadata to knowledge items:

await updateMetadata(
  knowledgeId,
  'FILE',
  {
    department: 'Sales',
    region: 'North America',
    accessLevel: '2'
  }
);

Track Document Versions

Maintain version tracking in metadata:

await updateMetadata(
  knowledgeId,
  'FILE',
  {
    version: '3.0',
    versionDate: '2025-01-16',
    changedBy: 'Jane Doe'
  }
);

Add Review Information

Track review status and reviewers:

await updateMetadata(
  knowledgeId,
  'URL',
  {
    reviewStatus: 'approved',
    reviewedBy: 'John Smith',
    reviewDate: '2025-01-16',
    nextReviewDate: '2025-04-16'
  }
);

Clean Up Old Metadata

Remove deprecated or temporary metadata fields:

await updateMetadata(
  knowledgeId,
  'FILE',
  {},
  ['tempField', 'deprecatedCategory', 'oldVersion']
);

Batch Update Metadata

Update metadata for multiple knowledge items:

async function batchUpdateMetadata(updates) {
  const results = [];
 
  for (const { knowledgeId, type, metadata } of updates) {
    try {
      const result = await updateMetadata(knowledgeId, type, metadata);
      results.push({ success: true, knowledgeId, result });
    } catch (error) {
      results.push({ success: false, knowledgeId, error: error.message });
    }
  }
 
  return results;
}
 
// Usage
const updates = [
  {
    knowledgeId: 'knowledge-1',
    type: 'FILE',
    metadata: { department: 'Engineering', version: '2.0' }
  },
  {
    knowledgeId: 'knowledge-2',
    type: 'URL',
    metadata: { category: 'Documentation', priority: 5 }
  }
];
 
const results = await batchUpdateMetadata(updates);

Important Notes

Metadata Merging

Metadata is merged with existing metadata, not replaced:

Existing metadata:

{
  "department": "Sales",
  "version": "1.0"
}

Update request:

{
  "metadata": {
    "version": "2.0",
    "priority": 5
  }
}

Result:

{
  "department": "Sales",
  "version": "2.0",
  "priority": 5
}

Type Validation

The type parameter must match the knowledge item's actual type. The API validates this to prevent accidental updates to the wrong item.

Status Requirement

Knowledge items must be in COMPLETED status to update metadata. Items that are still processing cannot be updated.

Reserved Fields

To update title or language, use the Update Reserved Fields endpoint instead. These fields are considered core properties and require special handling.

Vector Database Updates

When you update metadata, the changes are propagated to the vector database (Pinecone) to ensure search results reflect the updated metadata.

Best Practices

Use Consistent Key Names

Establish standard metadata key names across your organization:

// Good - consistent naming
await updateMetadata(knowledgeId, 'FILE', {
  department: 'Engineering',
  reviewedBy: 'Jane Doe',
  reviewDate: '2025-01-16'
});
 
// Avoid - inconsistent naming
await updateMetadata(knowledgeId, 'FILE', {
  dept: 'Engineering',          // Inconsistent abbreviation
  reviewer: 'Jane Doe',          // Different naming pattern
  review_date: '2025-01-16'      // Snake case vs camelCase
});

Validate Type Before Updating

Always verify the knowledge type before updating:

const knowledge = await getKnowledge(knowledgeId);
await updateMetadata(
  knowledgeId,
  knowledge.type,  // Use actual type
  metadata
);

Handle Errors Gracefully

Check for common error conditions:

try {
  await updateMetadata(knowledgeId, 'FILE', metadata);
} catch (error) {
  if (error.status === 403) {
    console.error('Knowledge not in completed status');
  } else if (error.status === 422) {
    console.error('Type mismatch - verify knowledge type');
  } else if (error.status === 400) {
    console.error('Invalid metadata format or reserved field');
  } else {
    console.error('Update failed:', error.message);
  }
}

Remove Metadata Carefully

Verify keys exist before removing:

const knowledge = await getKnowledge(knowledgeId);
const keysToRemove = ['oldField', 'deprecatedField'].filter(key =>
  knowledge.metadata.hasOwnProperty(key)
);
 
if (keysToRemove.length > 0) {
  await updateMetadata(knowledgeId, knowledge.type, {}, keysToRemove);
}

Related Endpoints