Resolved conflicts: - CHANGELOG.md: Combined detailed v0.1.0 with new v0.2.0 release notes - CLAUDE.md: Kept development version for consistency Brings in all Phase 2 features: - Async/await support - Caching layer - Batch operations - Complete API coverage (Users, Groups, Assets) - Comprehensive documentation updates
18 KiB
API Reference
Complete reference for the Wiki.js Python SDK.
Table of Contents
Client
WikiJSClient
The main client class for interacting with Wiki.js API.
from wikijs import WikiJSClient
client = WikiJSClient(
base_url="https://wiki.example.com",
auth="your-api-key",
timeout=30,
verify_ssl=True,
user_agent="Custom-Agent/1.0"
)
Parameters
- base_url (
str): The base URL of your Wiki.js instance - auth (
str | AuthHandler): Authentication (API key string or auth handler) - timeout (
int, optional): Request timeout in seconds (default: 30) - verify_ssl (
bool, optional): Whether to verify SSL certificates (default: True) - user_agent (
str, optional): Custom User-Agent header - cache (
BaseCache, optional): Cache instance for response caching (default: None)
Methods
test_connection()
Test connection to Wiki.js instance.
is_connected = client.test_connection()
Returns: bool - True if connection successful
Raises:
ConfigurationError: If client is not properly configuredConnectionError: If cannot connect to serverAuthenticationError: If authentication fails
close()
Close the HTTP session and clean up resources.
client.close()
Context Manager Support
with WikiJSClient("https://wiki.example.com", auth="api-key") as client:
pages = client.pages.list()
# Session automatically closed
Authentication
API Key Authentication
from wikijs.auth import APIKeyAuth
auth = APIKeyAuth("your-api-key")
client = WikiJSClient("https://wiki.example.com", auth=auth)
JWT Authentication
JWT authentication uses token-based authentication with automatic refresh capabilities.
from wikijs.auth import JWTAuth
# Initialize with JWT token and refresh token
auth = JWTAuth(
token="eyJ0eXAiOiJKV1QiLCJhbGc...",
base_url="https://wiki.example.com",
refresh_token="refresh_token_here", # Optional: for automatic token refresh
expires_at=1234567890 # Optional: Unix timestamp of token expiration
)
client = WikiJSClient("https://wiki.example.com", auth=auth)
Parameters:
- token (
str): The JWT token string - base_url (
str): Wiki.js instance URL (needed for token refresh) - refresh_token (
str, optional): Refresh token for automatic renewal - expires_at (
float, optional): Token expiration timestamp (Unix timestamp)
Features:
- Automatic token expiration detection
- Automatic token refresh when refresh token is provided
- Configurable refresh buffer (default: 5 minutes before expiration)
- Token masking in logs for security
Caching
The SDK supports intelligent caching to reduce API calls and improve performance.
MemoryCache
In-memory LRU cache with TTL (time-to-live) support.
from wikijs import WikiJSClient
from wikijs.cache import MemoryCache
# Create cache with 5 minute TTL and max 1000 items
cache = MemoryCache(ttl=300, max_size=1000)
# Enable caching on client
client = WikiJSClient(
"https://wiki.example.com",
auth="your-api-key",
cache=cache
)
# First call hits the API
page = client.pages.get(123)
# Second call returns from cache (instant)
page = client.pages.get(123)
# Get cache statistics
stats = cache.get_stats()
print(f"Hit rate: {stats['hit_rate']}")
print(f"Cache size: {stats['current_size']}/{stats['max_size']}")
Parameters
- ttl (
int, optional): Time-to-live in seconds (default: 300 = 5 minutes) - max_size (
int, optional): Maximum number of cached items (default: 1000)
Methods
get(key: CacheKey) → Optional[Any]
Retrieve value from cache if not expired.
set(key: CacheKey, value: Any) → None
Store value in cache with TTL.
delete(key: CacheKey) → None
Remove specific value from cache.
clear() → None
Clear all cached values.
invalidate_resource(resource_type: str, identifier: Optional[str] = None) → None
Invalidate cache entries for a resource type.
# Invalidate specific page
cache.invalidate_resource('page', '123')
# Invalidate all pages
cache.invalidate_resource('page')
get_stats() → dict
Get cache performance statistics.
stats = cache.get_stats()
# Returns: {
# 'ttl': 300,
# 'max_size': 1000,
# 'current_size': 245,
# 'hits': 1523,
# 'misses': 278,
# 'hit_rate': '84.54%',
# 'total_requests': 1801
# }
cleanup_expired() → int
Manually remove expired entries. Returns number of entries removed.
Cache Behavior
- GET operations are cached (e.g.,
pages.get(),users.get()) - Write operations (create, update, delete) automatically invalidate cache
- LRU eviction: Least recently used items removed when cache is full
- TTL expiration: Entries automatically expire after TTL seconds
Pages API
Access the Pages API through client.pages.
list()
List pages with optional filtering and pagination.
pages = client.pages.list(
limit=10,
offset=0,
search="query",
tags=["tag1", "tag2"],
locale="en",
author_id=1,
order_by="title",
order_direction="ASC"
)
Parameters
- limit (
int, optional): Maximum number of pages to return - offset (
int, optional): Number of pages to skip - search (
str, optional): Search term to filter pages - tags (
List[str], optional): List of tags to filter by - locale (
str, optional): Locale to filter by - author_id (
int, optional): Author ID to filter by - order_by (
str, optional): Field to order by (title,created_at,updated_at,path) - order_direction (
str, optional): Order direction (ASCorDESC)
Returns: List[Page] - List of Page objects
Raises:
APIError: If the API request failsValidationError: If parameters are invalid
get()
Get a specific page by ID.
page = client.pages.get(123)
Parameters
- page_id (
int): The page ID
Returns: Page - Page object
Raises:
APIError: If the page is not found or request failsValidationError: If page_id is invalid
get_by_path()
Get a page by its path.
page = client.pages.get_by_path("getting-started", locale="en")
Parameters
- path (
str): The page path - locale (
str, optional): The page locale (default: "en")
Returns: Page - Page object
Raises:
APIError: If the page is not found or request failsValidationError: If path is invalid
create()
Create a new page.
from wikijs.models import PageCreate
new_page_data = PageCreate(
title="Getting Started",
path="getting-started",
content="# Welcome\n\nThis is your first page!",
description="Getting started guide",
tags=["guide", "tutorial"],
is_published=True
)
created_page = client.pages.create(new_page_data)
Parameters
- page_data (
PageCreate | dict): Page creation data
Returns: Page - Created Page object
Raises:
APIError: If page creation failsValidationError: If page data is invalid
update()
Update an existing page.
from wikijs.models import PageUpdate
update_data = PageUpdate(
title="Updated Title",
content="Updated content",
tags=["updated"]
)
updated_page = client.pages.update(123, update_data)
Parameters
- page_id (
int): The page ID - page_data (
PageUpdate | dict): Page update data
Returns: Page - Updated Page object
Raises:
APIError: If page update failsValidationError: If parameters are invalid
delete()
Delete a page.
success = client.pages.delete(123)
Parameters
- page_id (
int): The page ID
Returns: bool - True if deletion was successful
Raises:
APIError: If page deletion failsValidationError: If page_id is invalid
search()
Search for pages by content and title.
results = client.pages.search("search query", limit=10)
Parameters
- query (
str): Search query string - limit (
int, optional): Maximum number of results to return - locale (
str, optional): Locale to search in
Returns: List[Page] - List of matching Page objects
Raises:
APIError: If search failsValidationError: If parameters are invalid
get_by_tags()
Get pages by tags.
pages = client.pages.get_by_tags(
tags=["tutorial", "guide"],
match_all=True,
limit=10
)
Parameters
- tags (
List[str]): List of tags to search for - match_all (
bool, optional): If True, pages must have ALL tags (default: True) - limit (
int, optional): Maximum number of results to return
Returns: List[Page] - List of matching Page objects
Raises:
APIError: If request failsValidationError: If parameters are invalid
Batch Operations
Efficient methods for performing multiple operations in a single call.
create_many()
Create multiple pages efficiently.
from wikijs.models import PageCreate
pages_to_create = [
PageCreate(title="Page 1", path="page-1", content="Content 1"),
PageCreate(title="Page 2", path="page-2", content="Content 2"),
PageCreate(title="Page 3", path="page-3", content="Content 3"),
]
created_pages = client.pages.create_many(pages_to_create)
print(f"Created {len(created_pages)} pages")
Parameters:
- pages_data (
List[PageCreate | dict]): List of page creation data
Returns: List[Page] - List of created Page objects
Raises:
APIError: If creation fails (includes partial success information)ValidationError: If page data is invalid
Note: Continues creating pages even if some fail. Raises APIError with details about successes and failures.
update_many()
Update multiple pages efficiently.
updates = [
{"id": 1, "content": "New content 1"},
{"id": 2, "content": "New content 2", "title": "Updated Title 2"},
{"id": 3, "is_published": False},
]
updated_pages = client.pages.update_many(updates)
print(f"Updated {len(updated_pages)} pages")
Parameters:
- updates (
List[dict]): List of dicts with 'id' and fields to update
Returns: List[Page] - List of updated Page objects
Raises:
APIError: If updates fail (includes partial success information)ValidationError: If update data is invalid (missing 'id' field)
Note: Each dict must contain an 'id' field. Continues updating even if some fail.
delete_many()
Delete multiple pages efficiently.
result = client.pages.delete_many([1, 2, 3, 4, 5])
print(f"Deleted: {result['successful']}")
print(f"Failed: {result['failed']}")
if result['errors']:
print(f"Errors: {result['errors']}")
Parameters:
- page_ids (
List[int]): List of page IDs to delete
Returns: dict with keys:
successful(int): Number of successfully deleted pagesfailed(int): Number of failed deletionserrors(List[dict]): List of errors with page_id and error message
Raises:
APIError: If deletions fail (includes detailed error information)ValidationError: If page IDs are invalid
Performance Benefits:
- Reduces network overhead for bulk operations
- Partial success handling prevents all-or-nothing failures
- Detailed error reporting for debugging
Models
Page
Represents a Wiki.js page with all metadata and content.
from wikijs.models import Page
Properties
- id (
int): Unique page identifier - title (
str): Page title - path (
str): Page path/slug - content (
str): Page content - description (
str, optional): Page description - is_published (
bool): Whether page is published - is_private (
bool): Whether page is private - tags (
List[str]): Page tags - locale (
str): Page locale - author_id (
int, optional): Author ID - author_name (
str, optional): Author name - author_email (
str, optional): Author email - editor (
str, optional): Editor used - created_at (
datetime): Creation timestamp - updated_at (
datetime): Last update timestamp
Computed Properties
# Word count
word_count = page.word_count
# Reading time (minutes)
reading_time = page.reading_time
# Full URL path
url_path = page.url_path
Methods
# Extract markdown headings
headings = page.extract_headings()
# Check if page has a tag
has_tutorial_tag = page.has_tag("tutorial")
PageCreate
Data model for creating a new page.
from wikijs.models import PageCreate
page_data = PageCreate(
title="New Page",
path="new-page",
content="Page content",
description="Optional description",
is_published=True,
is_private=False,
tags=["tag1", "tag2"],
locale="en",
editor="markdown"
)
Required Fields
- title (
str): Page title - path (
str): Page path/slug - content (
str): Page content
Optional Fields
- description (
str): Page description - is_published (
bool): Whether to publish immediately (default: True) - is_private (
bool): Whether page should be private (default: False) - tags (
List[str]): Page tags (default: []) - locale (
str): Page locale (default: "en") - editor (
str): Editor to use (default: "markdown")
PageUpdate
Data model for updating an existing page.
from wikijs.models import PageUpdate
update_data = PageUpdate(
title="Updated Title",
content="Updated content",
tags=["new-tag"]
)
Optional Fields (all)
- title (
str): Page title - content (
str): Page content - description (
str): Page description - is_published (
bool): Publication status - is_private (
bool): Privacy status - tags (
List[str]): Page tags
Exceptions
APIError
Base exception for API-related errors.
from wikijs.exceptions import APIError
try:
page = client.pages.get(999)
except APIError as e:
print(f"API error: {e}")
AuthenticationError
Raised when authentication fails.
from wikijs.exceptions import AuthenticationError
try:
client.test_connection()
except AuthenticationError as e:
print(f"Authentication failed: {e}")
ValidationError
Raised when input validation fails.
from wikijs.exceptions import ValidationError
try:
page_data = PageCreate(title="", path="invalid path")
except ValidationError as e:
print(f"Validation error: {e}")
ConfigurationError
Raised when client configuration is invalid.
from wikijs.exceptions import ConfigurationError
try:
client = WikiJSClient("", auth=None)
except ConfigurationError as e:
print(f"Configuration error: {e}")
ConnectionError
Raised when connection to Wiki.js fails.
from wikijs.exceptions import ConnectionError
try:
client.test_connection()
except ConnectionError as e:
print(f"Connection error: {e}")
TimeoutError
Raised when requests timeout.
from wikijs.exceptions import TimeoutError
try:
pages = client.pages.list()
except TimeoutError as e:
print(f"Request timed out: {e}")
Utilities
URL Utilities
from wikijs.utils import normalize_url, build_api_url
# Normalize a base URL
normalized = normalize_url("https://wiki.example.com/")
# Build API endpoint URL
api_url = build_api_url("https://wiki.example.com", "/graphql")
Response Utilities
from wikijs.utils import parse_wiki_response, extract_error_message
# Parse Wiki.js API response
data = parse_wiki_response(response_data)
# Extract error message from HTTP response
error_msg = extract_error_message(http_response)
Error Handling Best Practices
Comprehensive Error Handling
from wikijs import WikiJSClient
from wikijs.exceptions import (
APIError,
AuthenticationError,
ValidationError,
ConnectionError,
TimeoutError
)
try:
client = WikiJSClient("https://wiki.example.com", auth="api-key")
pages = client.pages.list(limit=10)
except AuthenticationError:
print("Invalid API key or authentication failed")
except ValidationError as e:
print(f"Invalid parameters: {e}")
except ConnectionError:
print("Cannot connect to Wiki.js instance")
except TimeoutError:
print("Request timed out")
except APIError as e:
print(f"API error: {e}")
Retry Logic
import time
from wikijs.exceptions import TimeoutError, ConnectionError
def with_retry(func, max_retries=3, delay=1):
for attempt in range(max_retries):
try:
return func()
except (TimeoutError, ConnectionError) as e:
if attempt == max_retries - 1:
raise
time.sleep(delay * (2 ** attempt)) # Exponential backoff
# Usage
pages = with_retry(lambda: client.pages.list())
Performance Tips
Connection Reuse
# Use context manager for automatic cleanup
with WikiJSClient("https://wiki.example.com", auth="api-key") as client:
# Multiple operations reuse the same connection
pages = client.pages.list()
page = client.pages.get(123)
updated = client.pages.update(123, data)
Pagination
# Efficiently paginate through large result sets
def get_all_pages(client, batch_size=50):
offset = 0
all_pages = []
while True:
batch = client.pages.list(limit=batch_size, offset=offset)
if not batch:
break
all_pages.extend(batch)
offset += batch_size
return all_pages
Filtering
# Use server-side filtering instead of client-side
# Good: Filter on server
tutorial_pages = client.pages.get_by_tags(["tutorial"])
# Better: Combine filters
recent_tutorials = client.pages.list(
tags=["tutorial"],
order_by="updated_at",
order_direction="DESC",
limit=10
)