Plugin Development
Karrioβs plugin system is the cornerstone of its extensibility, allowing you to seamlessly integrate custom carriers, address validators, and other third-party services. This guide provides a comprehensive overview of how to develop, structure, and register plugins with Karrio.
Plugin Types
Karrio is designed to support a variety of plugin types, including:
- Carrier Integrations: Connect to any shipping carrierβs API. This is the most common plugin type.
- Address Validators: Integrate third-party address verification services.
- Upcoming: Duty & Tax Calculators, Insurance Providers, and Payment Services.
Plugin Development Approaches
Karrio supports two methods for developing and registering plugins:
- Directory-based plugins: The traditional method where plugins are loaded from a specific local directory. This is ideal for private, in-house integrations.
- Entrypoint-based plugins: The modern, recommended method where plugins are distributed as standard Python packages and registered via entrypoints. This is best for open-source or publicly distributed plugins.
Directory-Based Plugins
Directory-based plugins are loaded from a local folder and do not require a full Python package setup, making them quick to create and test.
Directory Structure
A valid plugin directory must contain a karrio
sub-directory, which mirrors the structure of a native Karrio integration:
1/your_plugins_folder/ 2βββ my_carrier/ 3 βββ karrio/ 4 βββ mappers/ 5 β βββ my_carrier/ 6 β βββ __init__.py # Contains the legacy METADATA object (optional) 7 β βββ mapper.py 8 β βββ proxy.py 9 β βββ settings.py 10 βββ providers/ 11 β βββ my_carrier/ 12 β βββ __init__.py 13 β βββ rate.py 14 β βββ ... 15 βββ schemas/ 16 βββ my_carrier/ 17 βββ ...
Loading Directory-Based Plugins
Karrio can load plugins from a directory specified in one of two ways:
- Default
plugins
directory: Place your plugin folder (e.g.,my_carrier
) inside a directory namedplugins
in your current working directory. KARRIO_PLUGINS
Environment Variable: Set theKARRIO_PLUGINS
environment variable to the absolute path of your plugins folder.1export KARRIO_PLUGINS=/path/to/your_plugins_folder
Entrypoint-Based Plugins
This is the standard and recommended approach for creating distributable plugins. Your plugin is built as a standard Python package and registered with Karrioβs plugin system using a pyproject.toml
entrypoint.
Package Structure
The internal structure of your package should follow the standard Karrio extension format:
1/karrio-my-carrier/ 2βββ pyproject.toml 3βββ karrio/ 4 βββ plugins/ 5 βββ my_carrier/ 6 βββ __init__.py # Contains the METADATA object
Registering the Plugin
In your pyproject.toml
, you define an entrypoint under the karrio.plugins
group. This tells Karrio where to find your pluginβs METADATA
.
pyproject.toml1[project.entry-points."karrio.plugins"] 2my_carrier = "karrio.plugins.my_carrier"
The key (my_carrier
) is the unique identifier for your plugin, and the value (karrio.plugins.my_carrier
) is the Python path to the module containing the METADATA
object.
Installing the Plugin
Install your package in editable mode during development:
1pip install -e .
Karrio will automatically discover and load the plugin upon restart.
Plugin Metadata
Every plugin, regardless of type, must define a METADATA
object. This object, an instance of PluginMetadata
, is the manifest that describes your plugin to Karrio.
Example: Carrier Integration Metadata
For a carrier, the METADATA
object references the Mapper
and Settings
classes.
karrio/plugins/my_carrier/__init__.py1from karrio.core.metadata import PluginMetadata 2from karrio.mappers.my_carrier.mapper import Mapper 3from karrio.mappers.my_carrier.settings import Settings 4 5METADATA = PluginMetadata( 6 # Core properties 7 id="my_carrier", 8 label="My Carrier", 9 10 # Integration Schemas 11 Mapper=Mapper, 12 Settings=Settings, 13 14 # Optional metadata 15 is_hub=False 16)
Example: Address Validator Metadata
For an address validator, the METADATA
object references the Validator
and Settings
classes.
karrio/plugins/my_validator/__init__.py1from karrio.core.metadata import PluginMetadata 2from karrio.validators.my_validator.validator import Validator 3from karrio.validators.my_validator.settings import Settings 4 5METADATA = PluginMetadata( 6 # Core properties 7 id="my_validator", 8 label="My Validator", 9 10 # Integration Schemas 11 Validator=Validator, 12 Settings=Settings, 13)
Plugin Discovery Flow
Karrioβs plugin loading mechanism is designed to be robust and flexible.
Precedence: If plugins with the same id
are found in multiple locations, Karrio uses the following order of precedence (first one found wins):
- Entrypoint-based plugins
- Plugins from
KARRIO_PLUGINS
- Plugins from the default
./plugins
directory
Testing Your Plugin
- For Directory-based plugins: Place your plugin in one of the specified directories and restart the Karrio server.
- For Entrypoint-based plugins: Install your package in editable mode (
pip install -e .
) and restart the Karrio server.
Check the Karrio server logs on startup to confirm that your plugin was successfully discovered and loaded.
Troubleshooting
If your plugin isnβt loading:
- Check Logs: Karrio logs any errors encountered during plugin discovery.
- Verify Structure: Ensure your directory structure and
METADATA
object are correct. - Confirm Installation: For entrypoint plugins, double-check that your package is properly installed in the Python environment (
pip list
).
Additional Resources
- Carrier Integration Guide: A deep dive into creating carrier-specific integrations.