Content API¶
The Content API allows you to manage documents and files in the Unique AI knowledge base.
Overview¶
The Content resource provides methods to:
- Search and retrieve content from the knowledge base
- Upload new documents and files
- Update existing content (title, location, metadata)
- Update content ingestion state
- Delete content
- Ingest magic table sheets
Methods¶
unique_sdk.Content.search - Search content with filtering
Load full content/files from the knowledge base with user rights and filtering.
Returns:
Returns a list of Content objects.
Parameters:
where(required) - Filter conditions usingContentWhereInputchatId(optional) - Filter content by chat IDincludeFailedContent(optional) - Include failed ingestion content
Example:
unique_sdk.Content.search(
user_id=userId,
company_id=companyId,
where={
"OR": [
{
"title": {
"contains": "42",
},
},
{
"key": {
"contains": "42",
},
},
],
},
chatId=chatId,
)
unique_sdk.Content.get_info - Get content info (Deprecated)
Deprecated
Use unique_sdk.Content.get_infos instead.
Get content info with UniqueQL metadata filtering.
Parameters:
metadataFilter(optional) - UniqueQL metadata filterskip(optional) - Number of entries to skip (default: 0)take(optional) - Number of entries to return (default: 50)filePath(optional) - Filter by file pathcontentId(optional) - Filter by content IDchatId(optional) - Filter by chat ID
Returns:
Returns a PaginatedContentInfo object.
Example:
content_info_result = unique_sdk.Content.get_info(
user_id=user_id,
company_id=company_id,
metadataFilter={
"or": [
{
"and": [
{
"operator": "contains",
"path": ["folderIdPath"],
"value": "uniquepathid://scope_abcdibgznc4bkdcx120zm5d"
},
{
"operator": "contains",
"path": ["title"],
"value": "ai"
}
]
}
]
},
skip=0,
take=3,
)
unique_sdk.Content.get_infos - Get content infos
Get content infos with either UniqueQL metadata filter or parentId. Cannot use both simultaneously.
Parameters:
metadataFilter(optional) - UniqueQL metadata filter (cannot be used withparentId)parentId(optional) - Filter by parent folder/scope ID (cannot be used withmetadataFilter)parentFolderPath(optional) - Filter by parent folder path (alternative toparentId)skip(optional) - Number of entries to skip (default: 0)take(optional) - Number of entries to return (default: 50)
Returns:
Returns a PaginatedContentInfos object.
Example with Metadata Filter:
content_info_result = unique_sdk.Content.get_infos(
user_id=user_id,
company_id=company_id,
metadataFilter={
"or": [
{
"and": [
{
"operator": "contains",
"path": ["folderIdPath"],
"value": "uniquepathid://scope_abcdibgznc4bkdcx120zm5d"
},
{
"operator": "contains",
"path": ["title"],
"value": "ai"
}
]
}
]
},
skip=0,
take=3,
)
Example with Parent ID:
content_info_result = unique_sdk.Content.get_infos(
user_id=user_id,
company_id=company_id,
parentId="scope_ahefgj389srjbfejkkk98u"
)
Example with Parent Folder Path:
content_info_result = unique_sdk.Content.get_infos(
user_id=user_id,
company_id=company_id,
parentFolderPath="/Company/Reports/Q1"
)
unique_sdk.Content.upsert - Upload content
Upload new content to the knowledge base into a specific scope or chat.
Parameters:
input(required) - Content input object. SeeContent.Inputfor field details.scopeId(str, optional) - Scope ID to upload to (required ifchatIdorparentFolderPathnot provided)parentFolderPath(str, optional) - Folder path to upload to (alternative toscopeId). Creates the folder if it doesn't exist.createFolderIfNotExists(bool, optional) - Whether to create the folder if it doesn't exist (default:True)chatId(str, optional) - Chat ID to upload to (required ifscopeIdnot provided)sourceOwnerType(str, optional) - Source owner typestoreInternally(bool, optional) - Store file internallyfileUrl(str, optional) - External file URLreadUrl(str, optional) - Read URL for confirming upload (used in second call)
Returns:
Returns a Content object.
Example:
import os
import requests
def upload_file(
userId,
companyId,
path_to_file,
displayed_filename,
mimeType,
scope_or_unique_path,
description=None,
ingestion_config=None,
metadata=None,
):
size = os.path.getsize(path_to_file)
# Step 1: Create content and get upload URL
createdContent = unique_sdk.Content.upsert(
user_id=userId,
company_id=companyId,
input={
"key": displayed_filename,
"title": displayed_filename,
"mimeType": mimeType,
"description": description,
"ingestionConfig": ingestion_config,
"metadata": metadata,
},
scopeId=scope_or_unique_path,
)
uploadUrl = createdContent.writeUrl
# Step 2: Upload to Azure blob storage
with open(path_to_file, "rb") as file:
requests.put(
uploadUrl,
data=file,
headers={
"X-Ms-Blob-Content-Type": mimeType,
"X-Ms-Blob-Type": "BlockBlob",
},
)
# Step 3: Confirm upload with file size
unique_sdk.Content.upsert(
user_id=userId,
company_id=companyId,
input={
"key": displayed_filename,
"title": displayed_filename,
"mimeType": mimeType,
"description": description,
"byteSize": size,
"ingestionConfig": ingestion_config,
"metadata": metadata,
},
scopeId=scope_or_unique_path,
readUrl=createdContent.readUrl,
)
return createdContent
# Usage
createdContent = upload_file(
userId,
companyId,
"/path/to/file.pdf",
"test.pdf",
"application/pdf",
"scope_stcj2osgbl722m22jayidx0n",
ingestionConfig={
"chunkMaxTokens": 1000,
"uniqueIngestionMode": "INGESTION",
"chunkStrategy": "UNIQUE_DEFAULT_CHUNKING"
},
metadata={
"folderIdPath": "uniquepathid://scope_id"
}
)
Example with Folder Path (auto-creates folder):
content = unique_sdk.Content.upsert(
user_id=user_id,
company_id=company_id,
parentFolderPath="/Company/Reports/2024/Q1",
input={
"key": "quarterly-report.pdf",
"title": "Q1 2024 Report",
"mimeType": "application/pdf",
"byteSize": 1024,
},
)
unique_sdk.Content.ingest_magic_table_sheets - Ingest table sheets
Ingest a magic table sheet where each row is processed and converted into content.
Parameters:
data(List[MagicTableSheetTable], required) - List of table rows to ingest- Each row contains:
rowId(str) - Unique row identifiercolumns(List[MagicTableSheetTableColumn]) - List of column valuescolumnId(str) - Column identifiercolumnName(str) - Column namecontent(str) - Column content/text
ingestionConfiguration(MagicTableSheetIngestionConfiguration, required) - Configuration for ingestioncolumnIdsInMetadata(List[str]) - Column IDs to include in metadatacolumnIdsInChunkText(List[str]) - Column IDs to include in chunk textmetadata(Dict[str, Optional[str]], required) - Base metadata for all ingested contentscopeId(str, required) - Scope ID to ingest content intosheetName(str, required) - Name of the sheet being ingested
Returns:
Returns a MagicTableSheetResponse object.
Example:
params = {
"user_id": user_id,
"company_id": company_id,
"data": [
{
"rowId": "2",
"columns": [
{"columnId": "0", "columnName": "Section", "content": "Other"},
{"columnId": "1", "columnName": "Question", "content": "What do you know?"},
{
"columnId": "2",
"columnName": "Knowledge Base Answer",
"content": "Lorem Ipsum is simply dummy text.",
},
],
},
],
"ingestionConfiguration": {
"columnIdsInMetadata": ["1", "2"],
"columnIdsInChunkText": ["1", "2"],
},
"metadata": {
"libraryName": "foo",
},
"scopeId": scope_id,
"sheetName": "Sheet1",
}
unique_sdk.Content.ingest_magic_table_sheets(**params)
unique_sdk.Content.update - Update content
Compatibility
Compatible with release >.36
Update a file by its contentId or filePath.
Parameters:
contentId(str, optional) - ID of the file to update (required iffilePathnot provided)filePath(str, optional) - Absolute path of the file (required ifcontentIdnot provided)title(str, optional) - New file titleownerId(str, optional) - Move file to different folder using folder IDparentFolderPath(str, optional) - Move file to different folder using folder pathmetadata(Dict[str, str | None], optional) - Update file metadata (available in release >.40)
Returns:
Returns a ContentInfo object.
Examples:
Update title by path:
unique_sdk.Content.update(
user_id=user_id,
company_id=company_id,
filePath="/Company/finance/january.xls",
title="Revision Deck"
)
Move file by content ID:
unique_sdk.Content.update(
user_id=user_id,
company_id=company_id,
contentId="cont_ok2343q5owbce80w78hudawu5",
ownerId="scope_e68yz5asho7glfh7c7d041el",
metadata={
"quarter": "q1",
}
)
Move and update title:
unique_sdk.Content.update(
user_id=user_id,
company_id=company_id,
contentId="cont_ok2343q5owbce80w78hudawu5",
ownerId="scope_e68yz5asho7glfh7c7d041el",
title="Revision Deck (1)"
)
Move by folder path:
unique_sdk.Content.update(
user_id=user_id,
company_id=company_id,
contentId="cont_ok2343q5owbce80w78hudawu5",
parentFolderPath="/Company/Revisions"
)
unique_sdk.Content.update_ingestion_state - Update content ingestion state
Update the ingestion state of a content item. This can be used to re-queue content for ingestion or mark it with a specific state.
Parameters:
contentId(str, required) - ID of the content to updateingestionState(str, required) - The new ingestion state to set.
Returns:
Returns a ContentInfo object.
Example:
Re-queue content for ingestion:
unique_sdk.Content.update_ingestion_state(
user_id=user_id,
company_id=company_id,
contentId="cont_ok2343q5owbce80w78hudawu5",
ingestionState="QUEUED"
)
unique_sdk.Content.delete - Delete content
Compatibility
Compatible with release >.36
Delete a file by its contentId or filePath.
Parameters:
contentId(str, optional) - ID of the file to delete (required iffilePathnot provided)chatId(str, optional) - Chat ID (required if file is part of a chat)filePath(str, optional) - Absolute path of the file (required ifcontentIdnot provided)
Returns:
Returns a DeleteResponse object.
Examples:
Delete from chat:
unique_sdk.Content.delete(
user_id=user_id,
company_id=company_id,
contentId="cont_ok2343q5owbce80w78hudawu5",
chatId="chat_v3xfa7liv876h89vuiibus1"
)
Delete by path:
unique_sdk.Content.delete(
user_id=user_id,
company_id=company_id,
filePath="/Company/finance/january.xls",
)
Use Cases¶
For simplified file operations, use the File I/O utilities:
Upload Files
Instead of manually handling the three-step Content.upsert process, use the upload_file utility:
from unique_sdk.utils.file_io import upload_file
content = upload_file(
userId=user_id,
companyId=company_id,
path_to_file="/path/to/document.pdf",
displayed_filename="Q4_Report.pdf",
mime_type="application/pdf",
scope_or_unique_path="scope_abc123",
ingestion_config={
"chunkStrategy": "default",
"chunkMaxTokens": 1000
},
metadata={
"year": "2024",
"department": "Finance"
}
)
Download Files
Use the download_content utility to download files from the knowledge base:
from unique_sdk.utils.file_io import download_content
file_path = download_content(
companyId=company_id,
userId=user_id,
content_id="cont_abc123",
filename="report.pdf"
)
with open(file_path, "rb") as f:
content = f.read()
Wait for Ingestion Completion
After uploading a file, wait for it to be fully ingested before using it:
from unique_sdk.utils.file_io import upload_file, wait_for_ingestion_completion
import asyncio
async def upload_and_wait(file_path, scope_id):
content = upload_file(
userId=user_id,
companyId=company_id,
path_to_file=file_path,
displayed_filename="document.pdf",
mime_type="application/pdf",
scope_or_unique_path=scope_id
)
await wait_for_ingestion_completion(
user_id=user_id,
company_id=company_id,
content_id=content.id
)
return content
asyncio.run(upload_and_wait("/path/to/file.pdf", "scope_abc123"))
Filtering¶
ContentWhereInput¶
The ContentWhereInput type defines filter conditions for searching content. It supports logical operators (AND, OR, NOT) and field-specific filters
Available Fields:
id- Filter by content ID (usesStringFilter)key- Filter by file key/name (usesStringFilter)ownerId- Filter by owner/folder ID (usesStringFilter)title- Filter by content title (usesStringNullableFilter)url- Filter by content URL (usesStringNullableFilter)
Logical Operators:
AND- All conditions must match (array ofContentWhereInput)OR- Any condition must match (array ofContentWhereInput)NOT- Conditions must not match (array ofContentWhereInput)
String Filter Operators:
Each field filter supports the following operators:
contains(str) - Field contains the substringequals(str) - Field equals the value exactlystartsWith(str) - Field starts with the valueendsWith(str) - Field ends with the valuegt(str) - Field is greater than the valuegte(str) - Field is greater than or equal to the valuelt(str) - Field is less than the valuelte(str) - Field is less than or equal to the valuein_(List[str]) - Field is in the list of valuesnotIn(List[str]) - Field is not in the list of valuesnot_(NestedStringFilter) - Negate a nested filter conditionmode(QueryMode) - Query mode:"default"or"insensitive"(case-insensitive)
Examples:
Simple filter:
where={
"title": {
"contains": "report"
}
}
Multiple conditions with AND:
where={
"AND": [
{"title": {"contains": "report"}},
{"ownerId": {"equals": "scope_abc123"}}
]
}
Multiple conditions with OR:
where={
"OR": [
{"title": {"contains": "report"}},
{"key": {"contains": "report"}}
]
}
Case-insensitive search:
where={
"title": {
"contains": "Report",
"mode": "insensitive"
}
}
Using in_ operator:
where={
"id": {
"in_": ["cont_123", "cont_456", "cont_789"]
}
}
Complex nested conditions:
where={
"AND": [
{
"OR": [
{"title": {"contains": "report"}},
{"title": {"contains": "summary"}}
]
},
{
"NOT": [
{"ownerId": {"equals": "scope_excluded"}}
]
}
]
}
Input Types¶
Content.Input¶
The Content.Input type defines the structure for creating or updating content
Fields:
key(str, required) - File key/nametitle(str, optional) - Content titlemimeType(str, required) - MIME type (e.g., "application/pdf", "text/plain")description(str, optional) - Content descriptionownerType(str, optional) - Owner typeownerId(str, optional) - Owner/folder IDbyteSize(int, optional) - File size in bytesingestionConfig(IngestionConfig, optional) - Ingestion configurationmetadata(Dict[str, Any], optional) - Custom metadata dictionary
Used in: Content.upsert()
Return Types¶
Content¶
The Content object represents a full content item with chunks and URLs
Fields:
id(str) - Unique content identifierkey(str) - File key/nameurl(str | None) - Content URLtitle(str | None) - Content titleupdatedAt(str) - Last update timestamp (ISO 8601)chunks(List[Chunk] | None) - Document chunks with text and page informationmetadata(Dict[str, Any] | None) - Custom metadata dictionarywriteUrl(str | None) - URL for uploading file contentreadUrl(str | None) - URL for reading/downloading file contentexpiredAt(str | None) - Expiration timestamp (ISO 8601)appliedIngestionConfig(Dict[str, Any] | None) - The ingestion configuration that was applied to this content
Returned by: Content.search(), Content.upsert()
Chunk¶
The Chunk object represents a text chunk within a document
Fields:
id(str) - Chunk identifiertext(str) - Chunk text contentstartPage(int | None) - Starting page numberendPage(int | None) - Ending page numberorder(int | None) - Chunk order in document
Used in: Content.chunks
ContentInfo¶
The ContentInfo object represents basic information about a content item without full chunks.
Fields:
id(str) - Unique content identifierkey(str) - File key/nameurl(str | None) - Content URLtitle(str | None) - Content titlemetadata(Dict[str, Any] | None) - Custom metadata dictionarymimeType(str) - MIME type of the filedescription(str | None) - Content descriptionbyteSize(int) - File size in bytesownerId(str) - Owner/folder IDcreatedAt(str) - Creation timestamp (ISO 8601)updatedAt(str) - Last update timestamp (ISO 8601)expiresAt(str | None) - Expiration timestamp (ISO 8601)deletedAt(str | None) - Deletion timestamp (ISO 8601)expiredAt(str | None) - Expiration timestamp alias (ISO 8601)
Returned by: Content.get_info(), Content.get_infos(), Content.update()
PaginatedContentInfo¶
The PaginatedContentInfo object contains paginated content info results
Fields:
contentInfo(List[ContentInfo]) - List of content info objectstotalCount(int) - Total number of matching entries
Returned by: Content.get_info()
PaginatedContentInfos¶
The PaginatedContentInfos object contains paginated content infos results
Fields:
contentInfos(List[ContentInfo]) - List of content info objectstotalCount(int) - Total number of matching entries
Returned by: Content.get_infos()
MagicTableSheetResponse¶
The MagicTableSheetResponse object contains the mapping of row IDs to created content IDs
Fields:
rowIdsToContentIds(List[MagicTableSheetRowIdToContentId]) - Mapping of row IDs to created content IDs
MagicTableSheetRowIdToContentId Fields:
rowId(str) - Original row identifiercontentId(str) - Created content identifier
Returned by: Content.ingest_magic_table_sheets()
DeleteResponse¶
The DeleteResponse object contains the ID of deleted content
Fields:
id(str) - ID of the deleted content
Returned by: Content.delete()
Related Resources¶
- File I/O Utilities - Simplified file upload and download
- Folder API - Organize content into folders
- Search API - Search across content
- UniqueQL - Query language for filtering