Document Libraries provide a way to organize and manage collections of Document Sets in docpipe. A Document Library is a metadata container that groups related Document Sets together, enabling better organization, discovery, and management of your document collections.
A Document Library is a named collection that contains references to multiple Document Sets. It stores:
Important: Document Libraries store only metadata and references, not the actual document content or data.
Document Libraries follow a hybrid storage approach aligned with Document Sets pattern:
KeyValueStorage interface for library metadatadata column (CAMS-compatible)key, data (JSON), created_at, updated_atlibrary_documentset_junctionThis hybrid approach balances architectural consistency (JSON for assets) with performance (SQL for relationships).
# 1. Navigate to project root directory
cd /path/to/docling-pipelines
# 2. Activate virtual environment
source .venv/bin/activate
# 3. Set PYTHONPATH
export PYTHONPATH="$(pwd)/src:${PYTHONPATH}"
# 4. Ensure dependencies are installed
uv sync
Document Libraries are accessed via REST API endpoints. Start the API server:
# Recommended — uses the installed console entry point
docling-pipelines-api
# Alternative — invoke uvicorn directly (with PYTHONPATH set)
uvicorn docpipe.api.main:app --reload --host 0.0.0.0 --port 8000
The API will be available at http://localhost:8000 with interactive documentation at http://localhost:8000/api/v1/docs.
Note: The direct uvicorn command must be run from the project root with PYTHONPATH set to include the src directory.
Troubleshooting:
pkill -f "uvicorn docpipe.api.main:app"uvicorn docpipe.api.main:app --port 8001PYTHONPATH is set correctly and you’re in the project root directoryAll Document Library endpoints are under: /api/v1/document-libraries
Endpoint: POST /api/v1/document-libraries
Request Body:
{
"name": "Financial Documents Q1 2024",
"description": "Collection of financial documents for Q1 2024 analysis",
"tags": ["finance", "q1-2024", "reports"]
}
Validation Rules:
name: Required, 3-128 characters, must start with a letter, alphanumeric with spaces/underscores only (NO hyphens)description: Optional, max 2000 characterstags: Optional, no limit on count or individual tag lengthResponse (201 Created):
{
"library_id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Financial Documents Q1 2024",
"description": "Collection of financial documents for Q1 2024 analysis",
"tags": ["finance", "q1-2024", "reports"],
"document_set_ids": [],
"aggregate_metrics": {
"total_document_sets": 0,
"total_documents": 0,
"total_size_bytes": 0
},
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z"
}
Example using curl:
curl -X POST "http://localhost:8000/api/v1/document-libraries" \
-H "Content-Type: application/json" \
-d '{
"name": "Financial Documents Q1 20241",
"description": "Collection of financial documents for Q1 2024 analysis",
"tags": ["finance", "q1-2024", "reports"]
}'
Endpoint: GET /api/v1/document-libraries/{library_id}
Response (200 OK):
{
"library_id": "81cea322-ae1b-4142-8f27-e06ff39e211a",
"name": "Financial Documents Q1 20241",
"description": "Collection of financial documents for Q1 2024 analysis",
"purpose": null,
"original_size": null,
"final_size": null,
"tags": [
"finance",
"q1-2024",
"reports"
],
"created_by": null,
"href": null
}
Example using curl:
curl -X GET "http://localhost:8000/api/v1/document-libraries/550e8400-e29b-41d4-a716-446655440000"
Endpoint: PATCH /api/v1/document-libraries/{library_id}
Request Body:
name (required): Library name (3-128 characters, must start with letter, can only contain letters/digits/spaces/underscores)description (optional): Updated descriptionpurpose (optional): Updated purposeoriginal_size (optional): Updated original sizefinal_size (optional): Updated final sizetags (optional): Updated tags listNote: Name field is currently required even for PATCH operations. Name cannot contain hyphens or special characters.
{
"name": "Financial Documents Q1 2024 Updated",
"description": "Updated collection description",
"tags": ["finance", "q1_2024", "reports", "audited"]
}
Response (200 OK): Returns updated library object
Example using curl:
curl -X PATCH "http://localhost:8000/api/v1/document-libraries/550e8400-e29b-41d4-a716-446655440000" \
-H "Content-Type: application/json" \
-d '{
"name": "Financial Documents Q1 2024 Updated",
"description": "Updated collection description",
"tags": ["finance", "q1_2024", "reports", "audited"]
}'
Endpoint: DELETE /api/v1/document-libraries/{library_id}
Response (204 No Content)
Note: Deleting a library does not delete the associated Document Sets, only the library metadata and relationships.
Example using curl:
curl -X DELETE "http://localhost:8000/api/v1/document-libraries/550e8400-e29b-41d4-a716-446655440000"
Endpoint: PUT /api/v1/document-libraries/{library_id}/document-sets
Query Parameters:
document_sets_ids (required): Comma-separated list of document set UUIDsResponse (204 No Content): Document sets added successfully
Example using curl:
curl -X PUT "http://localhost:8000/api/v1/document-libraries/550e8400-e29b-41d4-a716-446655440000/document-sets?document_sets_ids=abc123,def456,ghi789"
Endpoint: DELETE /api/v1/document-libraries/{library_id}/document-sets
Query Parameters:
document_sets_ids (required): Comma-separated list of document set UUIDsResponse (204 No Content): Document sets removed successfully
Note: This removes the associations but does NOT delete the document sets themselves.
Example using curl:
curl -X DELETE "http://localhost:8000/api/v1/document-libraries/550e8400-e29b-41d4-a716-446655440000/document-sets?document_sets_ids=abc123,def456"
Endpoint: GET /api/v1/document-libraries
Query Parameters:
offset: Number of records to skip (default: 0)limit: Maximum number of records to return (default: 100)Response (200 OK):
[
{
"library_id": "e8b2cf35-4d2a-4997-b1e2-2470cd05fd73",
"name": "Financial Documents Q1 2024",
"description": "Collection of financial documents for Q1 2024 analysis",
"purpose": null,
"original_size": null,
"final_size": null,
"tags": [
"finance",
"q1-2024",
"reports"
],
"created_by": null,
"href": null
},
{
"library_id": "81cea322-ae1b-4142-8f27-e06ff39e211a",
"name": "Financial Documents Q1 20241",
"description": "Collection of financial documents for Q1 2024 analysis",
"purpose": null,
"original_size": null,
"final_size": null,
"tags": [
"finance",
"q1-2024",
"reports"
],
"created_by": null,
"href": null
}
]
Example using curl:
curl -X GET "http://localhost:8000/api/v1/document-libraries?offset=0&limit=10"
Endpoint: GET /api/v1/document-libraries/{library_id}/document-sets
Path Parameters:
library_id (required): UUID of the libraryResponse (200 OK):
{
"document_sets": [
{
"id": "f824b653-45af-45a6-9336-341c6aeb2d8a",
"name": "Research Documents1",
"container_id": null,
"container_type": null,
"description": "Collection of research papers and reports.",
"documents": null,
"tags": [],
"propagate_source_acls": null,
"is_derivative_available": null
},
{
"id": "85d7a47f-9d81-4ffe-a112-a93b88cd9c70",
"name": "Research Documents",
"container_id": null,
"container_type": null,
"description": "Collection of research papers and reports.",
"documents": null,
"tags": [],
"propagate_source_acls": null,
"is_derivative_available": null
}
]
}
Example using curl:
curl -X GET "http://localhost:8000/api/v1/document-libraries/550e8400-e29b-41d4-a716-446655440000/document-sets"
import requests
import json
class DocumentLibraryClient:
def __init__(self, base_url: str = "http://localhost:8000"):
self.base_url = base_url
self.api_path = "/api/v1/document-libraries"
def create_library(self, name: str, description: str = None, tags: list = None):
"""Create a new document library"""
url = f"{self.base_url}{self.api_path}"
payload = {"name": name}
if description:
payload["description"] = description
if tags:
payload["tags"] = tags
response = requests.post(url, json=payload)
response.raise_for_status()
return response.json()
def get_library(self, library_id: str):
"""Get a document library by ID"""
url = f"{self.base_url}{self.api_path}/{library_id}"
response = requests.get(url)
response.raise_for_status()
return response.json()
def update_library(self, library_id: str, name: str = None,
description: str = None, tags: list = None):
"""Update a document library"""
url = f"{self.base_url}{self.api_path}/{library_id}"
payload = {}
if name:
payload["name"] = name
if description:
payload["description"] = description
if tags:
payload["tags"] = tags
response = requests.patch(url, json=payload)
response.raise_for_status()
return response.json()
def delete_library(self, library_id: str):
"""Delete a document library"""
url = f"{self.base_url}{self.api_path}/{library_id}"
response = requests.delete(url)
response.raise_for_status()
def add_document_sets(self, library_id: str, document_set_ids: list[str]):
"""Add document sets to a library (bulk operation)"""
url = f"{self.base_url}{self.api_path}/{library_id}/document-sets"
params = {"document_sets_ids": ",".join(document_set_ids)}
response = requests.put(url, params=params)
response.raise_for_status()
def remove_document_sets(self, library_id: str, document_set_ids: list[str]):
"""Remove document sets from a library (bulk operation)"""
url = f"{self.base_url}{self.api_path}/{library_id}/document-sets"
params = {"document_sets_ids": ",".join(document_set_ids)}
response = requests.delete(url, params=params)
response.raise_for_status()
def list_document_sets(self, library_id: str):
"""List document sets in a library"""
url = f"{self.base_url}{self.api_path}/{library_id}/document-sets"
response = requests.get(url)
response.raise_for_status()
return response.json()
# Usage example
if __name__ == "__main__":
client = DocumentLibraryClient()
# Create a library
library = client.create_library(
name="Invoice Processing Library",
description="Collection of invoice document sets",
tags=["invoices", "accounting", "q1-2024"]
)
print(f"Created library: {library['library_id']}")
# Add document sets (bulk operation)
client.add_document_sets(library['library_id'], ["docset-001", "docset-002"])
# List document sets in library
doc_sets = client.list_document_sets(library['library_id'])
print(f"Library has {len(doc_sets['document_sets'])} document sets")
{
"detail": "Document library not found: 550e8400-e29b-41d4-a716-446655440000"
}
{
"detail": "Document library with name 'Financial Documents Q1 2024' already exists"
}
{
"detail": [
{
"loc": ["body", "name"],
"msg": "ensure this value has at least 3 characters",
"type": "value_error.any_str.min_length"
}
]
}
import requests
try:
response = requests.post(
"http://localhost:8000/api/v1/document-libraries",
json={"name": "My Library"}
)
response.raise_for_status()
library = response.json()
except requests.exceptions.HTTPError as e:
if e.response.status_code == 404:
print("Library not found")
elif e.response.status_code == 409:
print("Library already exists")
elif e.response.status_code == 422:
print(f"Validation error: {e.response.json()}")
else:
print(f"HTTP error: {e}")
except requests.exceptions.RequestException as e:
print(f"Request failed: {e}")
Symptom: 404 error when accessing a library
Solutions:
Symptom: 409 conflict error when creating a library
Solutions:
Symptom: 422 validation error
Solutions:
^[a-zA-Z][a-zA-Z0-9_ ]*$ (example: “My Library Name” or “Test_Library_123”)Symptom: Connection refused errors
Solutions:
uvicorn app.main:app --reloadThe Document Library feature uses a hybrid storage approach:
1. Library Metadata (KeyValueStorage - JSON):
CREATE TABLE document_libraries (
key VARCHAR PRIMARY KEY, -- library id
data JSON NOT NULL, -- Full library metadata as JSON
created_at TIMESTAMP NOT NULL,
updated_at TIMESTAMP NOT NULL
);
JSON Structure in data column:
{
"library_id": "uuid",
"name": "Library Name",
"description": "Description",
"purpose": "Purpose",
"tags": ["tag1", "tag2"],
"created_by": "user@example.com",
"href": "https://..."
}
2. Junction Table (Relational Storage):
CREATE TABLE library_documentset_junction (
library_id VARCHAR NOT NULL,
document_set_id VARCHAR NOT NULL,
added_at TIMESTAMP NOT NULL,
PRIMARY KEY (library_id, document_set_id)
);
Architecture Notes:
KeyValueStorage interface (same as Document Sets)The Document Library implementation follows hexagonal architecture (ports & adapters):
This architecture allows for:
For issues or questions:
http://localhost:8000/docs