πŸ“– Looking for karrio's legacy docs? Visit docs.karrio.io

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:

  1. Directory-based plugins: The traditional method where plugins are loaded from a specific local directory. This is ideal for private, in-house integrations.
  2. 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:

  1. Default plugins directory: Place your plugin folder (e.g., my_carrier) inside a directory named plugins in your current working directory.
  2. KARRIO_PLUGINS Environment Variable: Set the KARRIO_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.toml
1[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__.py
1from 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__.py
1from 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):

  1. Entrypoint-based plugins
  2. Plugins from KARRIO_PLUGINS
  3. Plugins from the default ./plugins directory

Testing Your Plugin

  1. For Directory-based plugins: Place your plugin in one of the specified directories and restart the Karrio server.
  2. 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