Public API Contract¶
VDL distinguishes between stable public API (safe to import and depend on) and internal implementation details that may change without warning.
Stable Public API¶
These imports and classes are supported across minor and patch versions. Use them freely in your applications and scripts.
Main Client and Config¶
from vdl import VDLClient, VDLConfig
The primary entry point for all download, playlist, discovery, and query operations.
Models (Safe to Import)¶
from vdl import (
# Status and configuration
DownloadStatus,
DownloadResult,
DownloadMetadata, # typed result metadata (replaces dict)
DownloadSidecars, # thumbnail and subtitle sidecar paths
IfExists,
SkipReason,
# Quality selection
Quality,
# Playlist operations
PlaylistInfo,
PlaylistItem,
# Planning and execution
AcquisitionPlan,
AcquisitionItem,
PlanKind,
BatchSummary,
# Crawling and discovery
CrawlerPolicy,
CrawlerDecision,
# Progress and cancellation
DownloadProgress,
# Health check
DoctorReport,
# State reconciliation
ReconciliationEntry,
ReconciliationReport,
)
Quality Selection¶
from vdl import Quality # now in public __all__
from vdl.models import Quality # also fine
# Quality options
Quality.BEST, Quality.P2160, Quality.P1440, Quality.P1080,
Quality.P720, Quality.P480, Quality.AUDIO
Progress Event¶
VDLClient.progress is a subscribable event for receiving progress updates across
all downloads on the client without threading a callback through every call:
client = VDLClient()
client.progress += my_async_handler # subscribe
client.progress -= my_async_handler # unsubscribe
Cancellation Control¶
from vdl.cancellation import CancellationToken, CancellationController
# Create a cancellation token to stop ongoing downloads
token = CancellationToken()
# Pass to download(), discover(), execute_plan()
# Call token.cancel() to trigger cancellation
Exception Hierarchy¶
from vdl import (
VDLError,
VDLConfigError,
VDLInputError,
VDLDownloadError,
VDLPlaylistError,
VDLStateError,
VDLDependencyError,
VDLSelectionError,
VDLCrawlerError,
)
# Catch by type to distinguish failure modes
try:
result = await client.download(url)
except VDLConfigError:
print("Configuration error")
except VDLDownloadError as e:
print(f"Download failed: {e}")
except VDLDependencyError:
print("Missing ffmpeg or yt-dlp")
Duplicate Detection Service¶
from vdl import DuplicateDetectionService, DuplicateDecision
# Available for preflight duplicate checks before download
service = client.execution_service.duplicate_detection
decision = await service.check(request)
Request Factory¶
from vdl import DownloadRequestFactory, DownloadRequest
# Build and customize download requests
factory = DownloadRequestFactory(config=config)
request = factory.create(url, quality=Quality.P720)
Logger Interface¶
from vdl import Logger, NullLogger
# Implement Logger to capture events
class MyLogger(Logger):
def log(self, level: str, event: str, **kwargs) -> None:
print(f"[{level}] {event}: {kwargs}")
# Wire into client
client = VDLClient(logger=MyLogger())
Runtime Components¶
from vdl.runtime import build_library_components, build_interactive_components
# Headless (stateless) wiring for CLI, scripts, libraries
components = build_library_components()
# Interactive (stateful) wiring with SQLite and logs
components = build_interactive_components()
Internal / Unstable APIs¶
The following modules are internal implementation details and may change without warning:
Core Implementation (DO NOT IMPORT)¶
vdl.core.* # All core modules and submodules
vdl.apps.* # CLI and MCP implementations
vdl.models (partially) # Some internal dataclass fields
Specific Internal Modules¶
Do not import from these; they are subject to refactoring:
# ✗ DON'T use these
from vdl.client import VDLClient # Use: from vdl import VDLClient
from vdl.config import VDLConfig # Use: from vdl import VDLConfig
from vdl.core.download.downloader import ...
from vdl.core.acquisition.planner import ...
from vdl.core.discovery.crawler import ...
from vdl.core.state.state import StateStore
from vdl.core.support.error_translation import ...
from vdl.core.retry import ...
from vdl.runtime import ... # Implementation detail
Hidden Implementation Details¶
Do not rely on internal class fields, private methods (prefixed with _), or undocumented attributes. These are:
- Internal service implementations (
YtDlpDownloader,SQLiteStateStore) - Private module-level variables
- Dataclass
__post_init__,__repr__, or internal fields - Protocol implementations (fakes for testing)
Forward Compatibility¶
What Guarantees Exist¶
- Public API function signatures are stable within a major version
- Enum values are stable (adding new values is okay, removing is not)
- Dataclass field order is stable (adding optional fields is okay, removing is not)
- Exception hierarchy is stable (adding new exception types is okay)
What May Change¶
- Private module implementations and internal functions
- Optional dataclass fields and their defaults
- Internal service wiring and component order
- Config file format and location (will be documented in release notes)
- CLI flags and subcommand behavior (use
--helpfor current state)
Version Compatibility¶
Use this in pyproject.toml or requirements.txt:
# Pins to a major version; accepts bug fixes and features
vdl = "^2.0.0"
# Or with optional MCP support
vdl = { version = "^2.0.0", extras = ["mcp"] }
Checking API Availability¶
To verify a public API is available, check the __all__ export in vdl/__init__.py:
from vdl import __all__
assert "VDLClient" in __all__
assert "DownloadResult" in __all__
See Also¶
- Architecture — module structure and boundaries
- Python API — usage examples and workflows
- AGENT_GUIDE.md — for AI agents and automation