# Document Management Documents are the primary data model in the Content Intelligence Platform. Each document is a JSON object that holds metadata as flexible name/value pairs — there is no fixed schema enforced at the storage layer, which allows content from diverse external systems (DAMs, cloud storage, SharePoint, Box, etc.) to be ingested without transformation. Documents exist within a graph-like structure where **nodes** (individual documents) and **edges** (links between documents) form a highly relational content model. For example, a `media` document can be linked to a `campaign` document, enabling hierarchical queries and relationship traversal across the content graph. **Document traits** define behavioral capabilities of a document type: | Trait | Description | |---|---| | `SUMMARY` | Document has a displayable summary representation | | `CHILDREN` | Document can contain child documents | | `TILE` | Document can be displayed as a tile/card | | `CONTENT` | Document is linked to binary content (files) | | `PREVIEW` | Document can generate a visual preview | | `INSIGHTS` | Document tracks engagement analytics | | `TIMELINE` | Document has a temporal lifecycle (start/end dates) | | `VERSION` | Document supports versioning | | `SOURCE` | Document tracks its originating content channel | **Endpoint reference:** - `create` — create one or more documents of a given kind, with optional external ID for deduplication - `retrieve` — fetch a document by ID with full metadata and linked content references - `list` — paginated listing of documents, filtered by kind, status, or metadata values - `query` — full-text and field-level search across the document graph - `query-within` — scoped search within a specific document hierarchy (e.g., within a brand or campaign) - `link / unlink` — create or remove typed edges between documents (e.g., link media to a campaign) - `retrieve-links` — traverse outbound edges from a document to its related documents - `update` — modify document metadata fields; uses partial update (only supplied fields change) - `delete / undelete` — soft-delete with restore; deleted documents remain queryable with a filter - `purge` — permanently remove a document and all its edges - `reindex` — trigger re-indexing of a document into OpenSearch; use after bulk imports or schema changes Documents reference binary content managed by the [Content Storage](#tag/Content-Storage) service and are typed using [Document Types](#tag/Document-Types) with optional schema enforcement via [Document Schemas](#tag/Document-Schemas). ## Create documents - [POST /api/v1/document/create](https://api.tenovos.com/openapi/content-intelligence/document-management/tenovos.document.documentservice.create.md): Creates one or more documents of a given kind, returning the IDs of newly created documents and any pre-existing duplicates. Request: documents - List of documents to create. Each entry includes: kind - The Kind name this document belongs to. doc - The document body as an arbitrary JSON value. externalId - Optional identifier from an external system for deduplication and cross-reference. Response: ids - IDs of the newly created documents. existingIds - IDs of pre-existing documents that matched by externalId (not re-created). ## Get documents - [POST /api/v1/document/retrieve](https://api.tenovos.com/openapi/content-intelligence/document-management/tenovos.document.documentservice.retrieve.md): Retrieves one or more documents by internal ID or external ID, with optional field projection and soft-delete inclusion. Request: ids - List of internal document IDs to retrieve. externalIds - List of external IDs to retrieve documents by. fetches - Optional field projection expression limiting which document fields are returned. includeDeleted - When true, includes soft-deleted documents in the results. Response: documents - List of Document objects (id, kind, doc body, timestamps). ## List documents - [POST /api/v1/document/list](https://api.tenovos.com/openapi/content-intelligence/document-management/tenovos.document.documentservice.list.md): Lists documents filtered by one or more kind names, with optional field projection and cursor-based pagination. Request: kinds - List of Kind names to filter by. fetches - Optional field projection expression limiting which document fields are returned. includeDeleted - When true, includes soft-deleted documents in the results. pagination - Optional Pagination cursor and page size. Response: documents - List of Document objects matching the filter. pageCursor - Opaque cursor for the next page. Absent when there are no further results. ## Link documents - [POST /api/v1/document/link](https://api.tenovos.com/openapi/content-intelligence/document-management/tenovos.document.documentservice.link.md): Creates directional links from a source document to one or more destination documents at a specified property path. Request: sourceId - ID of the document to link from. destIds - List of destination document IDs to link to. propertyPath - The field path on the source document that represents this relationship. destProperties - Optional per-destination properties. Each entry specifies destId and an optional weight used for ordering or scoring the relationship. Response: destIds - IDs of the destination documents that were successfully linked. ## Unlink documents - [POST /api/v1/document/unlink](https://api.tenovos.com/openapi/content-intelligence/document-management/tenovos.document.documentservice.unlink.md): Removes links from a source document to one or more destination documents at a specified property path. Request: sourceId - ID of the document to remove links from. destIds - List of destination document IDs to unlink. propertyPath - The field path on the source document where the links reside. Response: destIds - IDs of the destination documents that were successfully unlinked. ## Get document links - [POST /api/v1/document/retrieve-links](https://api.tenovos.com/openapi/content-intelligence/document-management/tenovos.document.documentservice.retrievelinks.md): Retrieves all outbound links for one or more source documents, returning destination IDs and property paths. Request: sourceIds - List of source document IDs whose links to retrieve. Response: docLinks - List of Links objects, one per source document. Each contains the sourceId and a list of Link entries (destId and propertyPath) representing all outbound relationships. ## Query documents - [POST /api/v1/document/query](https://api.tenovos.com/openapi/content-intelligence/document-management/tenovos.document.documentservice.query.md): Executes a structured query against all documents in the organization, returning matching results with full control over which fields and traits are returned, how results are filtered, and how pages are navigated. --- ## Query Language Queries are expressed as a single string using a structured query language with up to four clauses: fetch().orderBy(, asc|desc))] from([, ...]) [match('')] [filter()] Only fetch and from are required. match and filter are optional and may appear in any order after from. --- ## fetch() — Field and Trait Selection Specifies which fields or traits to return. Multiple items are comma-separated. | Syntax | Description | |---|---| | fetch(/) | Return the entire root document | | fetch(/field) | Return a single top-level field | | fetch(/field/subfield) | Return a nested field | | fetch($trait) | Return a trait result at the root | | fetch(/path/$trait) | Return a trait scoped to a field path | | fetch($trait$subtrait) | Return a trait with a sub-trait qualifier | | fetch($trait(key=value)) | Return a trait with attribute parameters | | fetch(/f1, $summary, /path/$preview) | Return multiple items | Ordering — append .orderBy(, asc|desc) to fetch(): fetch(/).orderBy(/name, asc) fetch($summary).orderBy(/createdAt, desc) Pagination — append .limit() or .limit(, ) to fetch(): fetch(/).limit(25) fetch(/).limit(25, nextPageToken) The cursor value is the opaque pageCursor string returned in the previous response. --- ## from() — Document Kind Selection Specifies one or more document kinds to query. Kind names must be lowercase letters and underscores only (3–62 characters). from(brand) from(asset, brand, region) Default platform kinds: media, brand, campaign, category, toolkit, section, block. Custom kinds defined in your organization are also supported. --- ## match() — Full-Text Search Performs a full-text keyword search across indexed document content. Keywords are provided as a single-quoted string. Results are ranked by relevance when orderBy is not specified. match('acme global') match('Q4 campaign hero') --- ## filter() — Field-Level Conditions Applies field-level conditions to narrow results. Expressions can be simple or compound. Comparison operators: | Operator | Meaning | |---|---| | == | Equals | | != | Not equals | | ` | Greater than | | >= | Greater than or equal | | ... | Contains (substring match or array membership) | | !.. | Does not contain | Logical operators: && (AND), || (OR), (...) (grouping) Literal value types: | Type | Syntax | Examples | |---|---|---| | Null | null | null | | Boolean | true / false | true | | Number | integer or decimal | 42, 3.14, -10 | | String | single-quoted | 'active', 'Acme Corp' | filter(/status == 'active') filter(/rating >= 4 && /region != null) filter((/status == 'active' || /status == 'pending') && /owner != null) filter(/tags ... 'featured') filter(/$$id == 'assetAbc123') Strings in filter conditions must be single-quoted. Supported escape sequences: \\, \', \n, \r, \t. --- ## Property Paths Property paths reference fields within a document and always begin with /. Nested fields are separated by /. | Path | Description | |---|---| | / | The root document | | /name | Top-level field | | /metadata/createdBy | Nested field | | /tags | Array field | | /$$id | Reserved system field (prefixed with $$) | Range selectors on link properties — link fields (relationships to other documents) support a range selector [start..end] to limit which linked items are returned. Both bounds are zero-based; start is inclusive, end is exclusive. | Syntax | Description | |---|---| | /items[0..5] | First 5 linked items | | /items[3..] | All linked items from index 3 onward | | /items[..10] | First 10 linked items | | /items[2..8] | Items at indices 2 through 7 | Ranges can appear at multiple levels of a path: fetch(/sections[0..3]/media[..10]) from(toolkit) --- ## Traits Traits define a standard contract for a set of fields a document kind can return. They are referenced in fetch() using the $ prefix. | Trait | Parameters | Returned Fields | |---|---|---| | $summary | — | name, description | | $tile | — | fgColor, bgColor, iconUrl | | $children | limit (optional) | items (array), depth | | $content | — | id, mimeType, contentType, size, filename, description, caption; plus type-specific: image (width, height), video (width, height, durationMs), document (width, height, pages) | | $preview | w, h, representationType | id, url | | $insights | — | Array of insight metrics (single value or timeseries) | | $timeline | — | from, to (timestamps) | | $version | — | number, isLatest | Sub-traits apply a secondary trait to each item returned by the parent: fetch($children$summary) # fetch children, return $summary for each fetch($children$summary(limit=5)) # limit to 5 children --- ## Complete Examples # Fetch all fields from a single kind fetch(/) from(brand) # Fetch specific fields fetch(/name, /status, /region) from(asset) # Fetch a trait fetch($summary) from(brand) # Fetch multiple traits and fields fetch($summary, $tile, /metadata) from(brand) # Fetch a trait at a nested path fetch(/heroImage/$preview(w=800, h=600)) from(campaign) # Full-text search fetch($summary) from(asset) match('product launch 2024') # Filter by a field value fetch(/) from(asset) filter(/status == 'approved') # Filter with AND fetch($summary) from(asset) filter(/status == 'active' && /owner != null) # Filter with OR and grouping fetch($summary) from(asset) filter((/status == 'active' || /status == 'pending') && /region != null) # Contains / not-contains fetch(/) from(asset) filter(/tags ... 'featured') fetch(/) from(brand) filter(/name !.. 'draft') # Query multiple kinds fetch($summary) from(brand, region, asset) filter(/status == 'active') # Order and paginate fetch($summary).orderBy(/name, asc).limit(20) from(brand) # Continue from a cursor fetch($summary).orderBy(/name, asc).limit(20, nextPageCursorToken) from(brand) # Fetch linked items with a range fetch(/items[0..5]) from(category) # Nested ranges fetch(/sections[0..3]/media[..10]) from(toolkit) # Limit children with trait attribute fetch($children(limit=5)) from(category) # Combined: search, filter, order, paginate fetch($summary, $preview(w=400, h=300)).orderBy(/name, asc).limit(10, abc123) from(asset) match('campaign hero') filter(/status == 'active' && /region != null) --- ## Request Parameters | Parameter | Type | Required | Description | |---|---|---|---| | query | string | Yes | The query expression string | | verbose | boolean | No | When true, includes per-phase execution timing in the response (info field) | ## Response | Field | Description | |---|---| | documents | List of matching document objects | | pageCursor | Opaque token to pass to the next request to retrieve the next page; absent when no further pages exist | | info | Query timing breakdown by phase (match, filter, projection) — only present when verbose: true` | ## Search within a document - [POST /api/v1/document/query-within](https://api.tenovos.com/openapi/content-intelligence/document-management/tenovos.document.documentservice.querywithin.md): Performs a keyword search within the content of a specific document, returning a relevance-scored series of matching positions. This is distinct from the query endpoint, which searches across documents — query-within searches inside a single document's indexed content. This is most useful for long-form content where you want to locate specific passages, pages, or moments, for example: - Finding the page in a PDF where a keyword appears - Locating the timestamp in a video where a term is spoken - Searching within a large document's indexed text body ## Request Parameters | Parameter | Type | Required | Description | |---|---|---|---| | id | string | Yes | The ID of the document to search within | | keywords | string | Yes | The keyword or phrase to search for within the document's content | | minScore | number | No | Minimum relevance score threshold (0.0–1.0). Points scoring below this value are excluded from the response. Use to filter out low-confidence matches. | ## Response | Field | Description | |---|---| | series | A scored series of matching positions within the document | Each point in the series contains: | Field | Type | Description | |---|---|---| | score | number | Relevance score for this match (higher is more relevant) | | ref | integer or string | Position reference — an integer page index for paginated content (PDFs, slide decks), or a timecode string for time-based content (video, audio) | ## Example To find all moments in a video where "product launch" is mentioned, with a minimum relevance score of 0.5: json { "id": "doc01abc123", "keywords": "product launch", "minScore": 0.5 } The response series would contain entries like: json { "series": [ { "score": 0.92, "ref": "00:01:34" }, { "score": 0.71, "ref": "00:08:12" } ] } For a PDF, ref values would be zero-based page indices (0, 4, 11, etc.). ## Update documents - [POST /api/v1/document/update](https://api.tenovos.com/openapi/content-intelligence/document-management/tenovos.document.documentservice.update.md): Applies an ordered sequence of field-level patch operations to one or more existing documents. Patches are applied in the order supplied; if any patch in the sequence is invalid, the entire update for that document is rejected. Request: updates - List of documents to update. Each entry includes: id - The document ID to target. Either id or externalId must be supplied. externalId - The external system ID to target (alternative to id, useful when the document was created with an externalId for cross-system referencing). patches - Ordered list of patch operations. Field paths use forward-slash notation matching the document's field structure (e.g. /name or /metadata/status). Each patch is one of: Add(path, value) — sets a field that does not yet exist. Remove(path) — removes the field at the given path. Replace(path, value) — overwrites an existing field's value. Response: ids - IDs of the documents that were successfully updated. ## Delete documents - [POST /api/v1/document/delete](https://api.tenovos.com/openapi/content-intelligence/document-management/tenovos.document.documentservice.delete.md): Soft-deletes one or more documents; deleted documents remain retrievable when includeDeleted is set. Request: ids - List of internal document IDs to soft-delete. externalIds - List of external IDs to soft-delete by (alternative to ids). Response: ids - IDs of the documents that were successfully deleted. ## Restore deleted documents - [POST /api/v1/document/undelete](https://api.tenovos.com/openapi/content-intelligence/document-management/tenovos.document.documentservice.undelete.md): Restores one or more soft-deleted documents, making them active again. Request: ids - List of internal document IDs to restore. externalIds - List of external IDs to restore by (alternative to ids). Response: ids - IDs of the documents that were successfully restored. ## Permanently remove documents - [POST /api/v1/document/purge](https://api.tenovos.com/openapi/content-intelligence/document-management/tenovos.document.documentservice.purge.md): Permanently and irreversibly removes one or more documents, bypassing soft-delete. Request: ids - List of internal document IDs to permanently delete. externalIds - List of external IDs to permanently delete by (alternative to ids). Response: ids - IDs of the documents that were successfully purged. ## Reindex documents - [POST /api/v1/document/reindex](https://api.tenovos.com/openapi/content-intelligence/document-management/tenovos.document.documentservice.reindex.md): Triggers reindexing of all documents matching a given query expression, returning a cursor for paginated progress. Request: query - Query expression identifying the documents to reindex. Response: pageCursor - Cursor to pass in a subsequent request to continue reindexing the next page. Absent when reindexing is complete.