This is the full developer documentation for Kybernaut Help
# How can I help?
> Documentation and help center for Kybernaut WooCommerce plugins — Mailstep, Messenger, licensing and troubleshooting guides.
## Pick your plugin
[Section titled “Pick your plugin”](#pick-your-plugin)

### [Kybernaut Mailstep](/mailstep/)
Connect WooCommerce to the Mailstep fulfillment service — orders, statuses and stock synchronized automatically.
* [Plugin settings](/mailstep/settings/)
* [Stock synchronization](/mailstep/stock-synchronization/)
* [Resending an order to Mailstep](/mailstep/resend-order/)
* [Logging](/mailstep/logging/)
* [Developer filters](/mailstep/developer-filters/)
[Browse all Mailstep docs →](/mailstep/)

### [Kybernaut Messenger](/messenger/)
Send WooCommerce orders to the Messenger courier service and schedule pickups without leaving your store.
* [Plugin settings](/messenger/settings/)
* [Manually sending an order to Messenger](/messenger/manual-order-send/)
* [Developer filters and actions](/messenger/developer-filters/)
[Browse all Messenger docs →](/messenger/)
## Everything else
[Section titled “Everything else”](#everything-else)
[ Account & Billing](/account/)[ General guides](/general/)[ Get support](/support/)
### Didn’t find an answer?
Write to me and we’ll sort it out together as quickly as possible.
[Contact support](/support/)
# Account & Billing
> Manage your Freemius account, licenses, invoices and subscriptions for Kybernaut premium plugins.
Premium Kybernaut plugins are sold through [Freemius](https://freemius.com/) — a platform that handles checkout, licensing and billing. This section covers everything around your account and subscription.
## In this section
[Section titled “In this section”](#in-this-section)
* [Your user account](/account/user-account/)
* [Billing details and invoices](/account/billing-details-and-invoices/)
* [Cancelling a subscription](/account/cancel-subscription/)
* [Freemius and data processing](/account/freemius-data-processing/)
# Changing billing details and downloading invoices
> Change your Freemius billing details in your profile and download invoices for every purchase or renewal from your Orders History.
## Billing details
[Section titled “Billing details”](#billing-details)
Need to change or add billing details (for your entire Freemius account)? Fortunately that’s no problem at all — you can change them yourself in your profile.
1. Log in to your account at using the email you used to purchase the plugin.
2. Go to the **My Profile** section and fill in the required details – Organization/Company name, Tax/VAT ID, Billing E-mail, Phone, Address Line, City / Town, ZIP / Postal code, Country.
3. The changes are also applied retroactively to the invoices you’ll find in your **Orders History**, though of course adding a VAT ID after the fact doesn’t affect VAT that has already been charged — it only takes effect from your next invoice.

Setting your billing details
## Invoices
[Section titled “Invoices”](#invoices)
After every purchase or subscription renewal, you’ll receive an email with an invoice from Freemius (on our behalf). If you have trouble finding that email, you can download all of your previous invoices from your account.
First you’ll need to [log in](https://users.freemius.com/) with your credentials. If you don’t remember your password, you can follow [these instructions](/account/user-account/#forgotten-password) to reset it.
Once you’re logged in, go to the **Orders History** tab. There you can download an invoice for each of your payments by clicking the blue invoice icon labeled **Invoice**.

Overview of orders and invoices available for download
Note
If this is the first invoice you’re downloading from Freemius, you’ll probably need to fill in your billing address so it can appear on the invoice. To do that, follow [these instructions](/account/billing-details-and-invoices/#billing-details).
# Cancelling a subscription
> Cancel a plugin subscription in your Freemius account under Renewals & Billing so it no longer renews automatically.
If you no longer want to keep paying to use a plugin, you can cancel your subscription in your [account](/account/user-account/) – once cancelled, the subscription won’t renew automatically.
Danger
For some plugins (e.g. Kybernaut Mailstep), cancelling your subscription can mean a significant loss of functionality, since they’re billed as SaaS (Software as a Service) in exchange for the option of choosing a monthly subscription.
1. Log in to your account at (more in the help [here](/account/user-account/)).
2. Go to the **Renewals & Billing** section.
3. Select the license you want to cancel and click **Cancel Auto-Renew**.
# Freemius and data processing
> How Freemius resells our plugins on our behalf, what diagnostic data the SDK tracks, why it's collected, and how your privacy is handled.
Selling anything isn’t exactly simple – payment gateways, availability, invoices, subscription management and renewals, and more.
On top of that, selling plugin licenses adds the overhead of continuously checking license validity. You have to account for refunds, license upgrade/downgrade events, and so on. Maintaining that kind of infrastructure can easily become a full-time job.
That’s why I’d rather leave the maintenance of the licensing system to [Freemius](https://freemius.com) – a platform for selling digital products – and focus on the plugins themselves instead. Freemius has been on the market since 2014 and is a reliable partner to hundreds of plugin authors in the WordPress world.
## How does it work?
[Section titled “How does it work?”](#how-does-it-work)
When you buy one of our plugins, you pay Freemius, which acts as the reseller on our behalf. This means you provide your billing address and payment details to Freemius.
Note
When you buy something on eBay or Amazon, you’re often buying from various companies that advertise their products on those platforms. Freemius works similarly, but for digital products.
After your purchase, you’ll receive 2 emails from Freemius on our behalf:
1. an email containing your license key and instructions for downloading + installing
2. an email containing the login details for your Freemius account
Tip
You can use the same email address to buy plugins/themes from other authors who use Freemius. You’ll access all of those products under the same login.
## How are payments and plugins connected?
[Section titled “How are payments and plugins connected?”](#how-are-payments-and-plugins-connected)
While checkout is an important part of the buying process, license management and basic analytics matter too. Freemius helps with that as well.
Every plugin ships with the [Freemius Software Development Kit (SDK)](https://freemius.com/help/documentation/wordpress-sdk/), which takes care of the things mentioned above. In short, when you activate one of the plugins, you’ll be redirected to a screen powered by Freemius that asks for your permission to track some diagnostic data, which also includes the validity of your license.
## What data is tracked?
[Section titled “What data is tracked?”](#what-data-is-tracked)
The only sensitive data that’s stored is the administrator’s name and email. Nothing else concerning your company or your site’s users is tracked. The administrator’s email is important so I can contact you about any security updates, feature announcements, and so on. Tracking data is sent to Freemius after login and then every 24 hours (for as long as the plugin is active).
Note
You can keep sharing your website’s data without receiving my occasional emails. Just click the unsubscribe link in one of the emails, or [let me know](https://kybernaut.cz/kontakt/) in advance.
The exact scope of the tracked data is available in the Freemius FAQ [here](https://github.com/Freemius/data-concerns-faq/blob/master/faq-08.md). The list also explains why each individual data point is tracked.
## What is that data used for?
[Section titled “What is that data used for?”](#what-is-that-data-used-for)
I prefer to make decisions based on data rather than guesswork and “gut feelings.” Here are a few examples of why this data is invaluable:
* Knowing which versions of WordPress/PHP our customers use helps keep the code cleaner and shortens development time between releases.
* Knowing which languages customers use helps prioritize translations.
* Knowing which themes customers use lets us test compatibility before releasing new versions.
This list isn’t exhaustive, but it should give you an idea of why this type of data matters and how it can be useful to you as well when we have it.
## Further questions
[Section titled “Further questions”](#further-questions)
If you have further concerns about Freemius and privacy, you can start with their [data tracking FAQ](https://github.com/Freemius/data-concerns-faq). If you have even more questions, I’ll do my best to answer them – just [get in touch](https://kybernaut.cz/kontakt/).
# User account
> Log in to your Freemius account to manage subscriptions, billing details, and invoices, reset a forgotten password, or close the account.
As mentioned in the [article about Freemius](/account/freemius-data-processing/), after your first purchase you’ll receive an email with the login details for your Freemius account. You can use these credentials to log in to [Freemius](https://users.freemius.com/) itself, where you can manage your subscriptions, [billing details](/account/billing-details-and-invoices/), and more.
## Logging in to your account
[Section titled “Logging in to your account”](#logging-in-to-your-account)
You can log in to your account at . Once you’re logged in, you’ll land in your account dashboard, which looks roughly like this:

Account management
Once logged in, you can view your currently active subscriptions, your order history, your license keys and where they were activated, change your billing details, download invoices, and so on.
## Forgotten password
[Section titled “Forgotten password”](#forgotten-password)
If you’re having trouble logging in, you may have forgotten your billing email and/or password. I’ll try to help with a forgotten email if you [write to me](https://kybernaut.cz/kontakt/) with your license number and the site where it’s used, but you can reset your account password yourself.
Just go to the [password recovery page](https://users.freemius.com/store/3566/password/recover) in the Freemius dashboard (or, on the login screen, click **Forgot your password?** and have it sent to you again).
## Closing your account
[Section titled “Closing your account”](#closing-your-account)
If you no longer have any subscriptions and you’re absolutely certain you want to close your Freemius account completely, you can do so by clicking the red **Close account** button in the **My Profile** section of your account.
Danger
Closing your account means you’ll lose access to your downloaded files, license keys, order history, invoices, and other data. You’ll no longer receive feature or security updates for any of the paid products you’ve purchased, and paid features in some products may stop working.
# General guides
> Installation, debugging, developer snippets and answers that apply to all Kybernaut plugins.
Guides that apply to all Kybernaut plugins — installation and license activation, debugging techniques, and developer snippets.
## In this section
[Section titled “In this section”](#in-this-section)
* [Plugin installation](/general/plugin-installation/)
* [Useful snippets](/general/useful-snippets/)
* [Using a server cron instead of WP-Cron](/general/server-cron/)
* [Debugging with the Health Check plugin](/general/health-check-debugging/)
# Debugging with the Health Check plugin
> Track down a broken plugin or theme safely using the Health Check plugin's troubleshooting mode, without disrupting visitors on your live site.
When something breaks, it’s hard to tell which plugin or theme is causing the error. One way to find out is to deactivate all plugins and then reactivate them one by one until you hit the problem, **but that can break or disrupt your live site.**
Instead, I recommend using the Health Check plugin, available in the wordpress.org repository:
> [Health Check & Troubleshooting](https://wordpress.org/plugins/health-check/)
1. Install the plugin. (Go to Plugins → Add New → search for “Health Check” and install it.)
2. Activate the plugin.
3. Follow the troubleshooting steps below.
## Troubleshooting
[Section titled “Troubleshooting”](#troubleshooting)
Go to Tools → Site Health → Troubleshooting and click **Enable**. To exit troubleshooting mode, you have to disable it manually from the admin bar dropdown at the top, or log out.
Note
Troubleshooting mode is now on. It has **no effect on your site’s visitors** — they’ll browse it as usual — but for you it will look as if you’d just installed WordPress for the first time.
In the WP dashboard you can enable individual plugins or themes, which lets you find out what’s causing your site’s odd behavior. Keep in mind that **any settings changes you make are preserved even** after you turn off troubleshooting mode.
Now enable only the plugins you need to test or debug (for example WooCommerce + its extensions), and keep the default WP theme.
If everything works, it’s probably a conflict with your other plugins. Re-enable them one by one and find out when the site or the feature breaks again.
# Plugin installation
> Install and activate the plugin in WordPress in under two minutes using the Freemius email, your license key, and the Upload Plugin screen.
You can handle the simple installation and activation in under two minutes. I’ll gladly guide you through the whole process in a short tutorial video.

## The email with your details
[Section titled “The email with your details”](#the-email-with-your-details)
When you purchased the plugin, you received a thank-you email for your subscription from Freemius ([Who is Freemius?](/account/freemius-data-processing/)) with the subject “Thanks for subscribing”.
It contains all the important information:
1. a download link for the plugin
2. your license key
3. login details for [your account](/account/user-account/)
4. the documentation address and support contacts
5. your subscription details

## Uploading the plugin to WordPress and activating the license
[Section titled “Uploading the plugin to WordPress and activating the license”](#uploading-the-plugin-to-wordpress-and-activating-the-license)
1. Download the plugin’s zip file from the email (see above, point 1) and do not unzip it.
2. Log in to your WordPress admin, go to the **Plugins** tab and choose **Add New**.
3. Click the **Upload Plugin** button, which you’ll find right next to the page heading.
4. Select the installation file and click the **Install Now** button.
5. Once installed, you can activate the plugin right away with the **Activate Plugin** button.
6. You’ll then be prompted to enter your license key.
After that you’ll be redirected to the [plugin settings](/mailstep/settings/), which I cover in a separate article.
# How to use a server cron instead of WP-Cron
> Replace unreliable WP-Cron with a server cron job: disable WP-Cron in wp-config.php and schedule wp-cron.php on your host for reliable tasks.
Below is a guide on how to use your server’s cron instead of WordPress’s built-in cron function.
First, it’s worth explaining the difference between them:
* WP-Cron is a function that lets you schedule tasks to run at certain intervals. However, running those tasks depends on site traffic, which can be unreliable if your site doesn’t get regular visits to trigger the cron.
* A server cron is a system-level tool that can run tasks at certain intervals regardless of whether your site is being visited.
## 1. Disabling WP-Cron
[Section titled “1. Disabling WP-Cron”](#1-disabling-wp-cron)
First you need to disable the default WP-Cron. Open the `wp-config.php` file and add the following line of code:
```php
define('DISABLE_WP_CRON', true);
```
This prevents WordPress from running its cron tasks.
## 2. Setting up the cron on the server
[Section titled “2. Setting up the cron on the server”](#2-setting-up-the-cron-on-the-server)
Next, on your server/hosting you need to add a new cron job that will run the tasks WordPress used to handle. The exact steps for setting up a cron job depend on your hosting provider, but the process generally consists of the following steps:
* Access your server’s control panel or connect to the server via SSH.
* Find the “Cron Jobs” section.
* Add a new cron job with a URL pointing to the wp-cron.php file:
```plaintext
https://www.yoursite.com/wp-cron.php?doing_wp_cron
```
Replace `https://www.yoursite.com` with your site’s URL.
This command runs WordPress’s cron tasks at the specified intervals.
## 3. Testing and monitoring
[Section titled “3. Testing and monitoring”](#3-testing-and-monitoring)
After setting up the server cron, it’s important to test and monitor it to make sure the tasks run as expected. Here are a few things to keep in mind:
* Check your site’s error logs for any cron-related problems.
* Monitor your site’s performance and make sure the cron tasks aren’t causing any slowdowns.
* Test the cron job by scheduling it to run at a specific time and verifying that it runs as expected.
And that’s it! By using your server’s cron instead of WordPress’s cron, you can ensure scheduled tasks run reliably without depending on user traffic.
# Useful snippets
> Handy WooCommerce code snippets for the Kybernaut Mailstep plugin: validate the phone field and require a house number in the checkout address.
If you want to add extra functionality to your store, besides plugins you can also use pieces of code called snippets. You can add them to a child theme (a derived theme), if you use one, or with a plugin such as [Code Snippets](https://wordpress.org/plugins/code-snippets/), which lets you insert them even if you’re not a programmer.
Below are a few useful ones that may come in handy if you use the [Kybernaut Mailstep](https://kybernaut.cz/pluginy/kybernaut-mailstep/) plugin.
## Phone validation
[Section titled “Phone validation”](#phone-validation)
If you don’t use any phone-validation plugin, I recommend at least a basic restriction in the form of this snippet. When the data is submitted at Checkout, it verifies the minimum length and watches for invalid characters in the phone field.
```php
/**
* @snippet WooCommerce: Minimum phone number length
* @author Karolína Vyskočilová (https://kybernaut.cz)
* @testedwith WordPress 5.2 & WooCommmerce 3.7.0
*/
function my_theme_validate_phone( $fields, $errors ){
// Mild phone check, min 9 numbers
if ( ! preg_match('/^[+]?[0-9. -]{9,}$/', $fields['billing_phone']) && !empty( $fields['billing_phone'] ) ) {
$errors->add( 'validation', __( 'Phone number is not valid.', 'my-theme' ) );
}
}
add_action( 'woocommerce_after_checkout_validation', 'my_theme_validate_phone', 10, 2);
```
Tip
This snippet is just a basic safety net — it checks length and allowed characters, but it won’t add the country code, validate the number against the destination country’s format, or standardize numbers for your CRM, SMS gateway, or carrier. For a complete solution, check out my [Phone Validator & Formatter](https://woocommerce.com/products/phone-validator-and-formatter/) plugin — it automatically adds the country code, validates against the country’s format, and standardizes formatting across your store.
## House number validation
[Section titled “House number validation”](#house-number-validation)
The snippet checks whether at least one digit is present in the first address line, on the assumption that the sender didn’t forget to include the house number. Useful for GLS and other delivery services.
```php
/**
* @snippet WooCommerce: Street (first line) contains at least one digit (house number)
* @author Karolína Vyskočilová (https://kybernaut.cz)
* @testedwith WordPress 5.8 & WooCommmerce 5.5
*/
function my_theme_validate_street( $fields, $errors ){
if ( ! preg_match('/[0-9]+/', $fields['billing_address_1']) && !empty( $fields['billing_address_1'] ) ) {
$errors->add( 'validation', __( 'Street address must contain a house number.', 'my-theme' ) );
}
}
add_action( 'woocommerce_after_checkout_validation', 'my_theme_validate_street', 10, 2);
```
# Kybernaut Mailstep
> Connect your WooCommerce store to the Mailstep fulfillment service — orders, statuses and stock synchronized automatically.
**Kybernaut Mailstep** connects your WooCommerce store to the [Mailstep](https://www.mailstep.cz/) fulfillment service. Orders flow to the warehouse automatically, order statuses come back, and stock levels stay in sync.
## Start here
[Section titled “Start here”](#start-here)
1. [Plugin installation](/general/plugin-installation/)
2. [Plugin settings](/mailstep/settings/)
3. [Stock synchronization](/mailstep/stock-synchronization/)
## Useful links
[Section titled “Useful links”](#useful-links)
* [Plugin page & pricing](https://kybernaut.cz/en/plugins/kybernaut-mailstep/)
* [Changelog](https://kybernaut.cz/en/plugins/kybernaut-mailstep/changelog-kybernaut-mailstep/)
* [Get support](/support/)
# Downloading a beta version of the plugin
> How to enable and download beta versions of the plugin via your Freemius account, and how to disable them again once you've finished testing.
Danger
Only download a beta version if the plugin’s author has asked you to (for example, to fix a problem you reported). Beta versions still contain not-yet-final changes that may not be stable.
## Enabling beta versions
[Section titled “Enabling beta versions”](#enabling-beta-versions)
1. Go to your Freemius account (**WooCommerce → Settings → Mailstep** and the **Account** tab)
2. In the **Version** row, tick the **Subscribe to beta versions** checkbox and confirm the setting

Enabling beta versions in the account settings in the plugin detail
## Downloading a new beta version
[Section titled “Downloading a new beta version”](#downloading-a-new-beta-version)
If a new beta version is available, once beta versions are enabled you can install it right away by pressing the **Install update** button.

Install the available beta version
Alternatively, you can go to **Dashboard → Updates** and ask WordPress to check for updates.

Check again for available updates
## Disabling beta versions
[Section titled “Disabling beta versions”](#disabling-beta-versions)
Follow the same steps as in the [Enabling beta versions](/mailstep/beta-versions/#enabling-beta-versions) section, just untick the checkbox.
On a production site, I recommend unticking it as soon as you’ve finished testing – a beta version that’s already installed, with any fix it contains, won’t be uninstalled.
# Developer filters
> Reference of the WordPress filters and actions provided by the Mailstep plugin, with parameters, source locations, and code examples for developers.
If you can’t find a filter or action here that you need, [contact me](/support/) with where and how you’d like it added, and I’ll gladly do so, to keep future plugin updates safe.
## kbnt\_mailstep\_blocked\_statuses\_update
[Section titled “kbnt\_mailstep\_blocked\_statuses\_update”](#kbnt_mailstep_blocked_statuses_update)
The filter returns the order statuses for which the order status is no longer updated based on data from Mailstep.
```php
apply_filters('kbnt_mailstep_blocked_statuses_update', ['completed',
'failed', 'cancelled', 'refunded']);
```
### Parameters
[Section titled “Parameters”](#parameters)
* **$statuses** (array) Order statuses
### Source code
[Section titled “Source code”](#source-code)
The filter is located in the file *includes/class-kbnt-mailstep-orders.php*.
## kbnt\_mailstep\_cod\_payment\_methods
[Section titled “kbnt\_mailstep\_cod\_payment\_methods”](#kbnt_mailstep_cod_payment_methods)
The filter returns the slugs of payment methods that are considered cash on delivery.
```php
apply_filters('kbnt_mailstep_cod_payment_methods', ['cod', 'dobirka']);
```
### Parameters
[Section titled “Parameters”](#parameters-1)
* **$methods** (array) Slugs of payment methods considered cash on delivery.
### Source code
[Section titled “Source code”](#source-code-1)
The filter is located in the files *includes/class-kbnt-mailstep-api.php*, *includes/class-kbnt-mailstep-orders.php*.
## kbnt\_mailstep\_fallback\_couriers
[Section titled “kbnt\_mailstep\_fallback\_couriers”](#kbnt_mailstep_fallback_couriers)
Lets you introduce a fallback for couriers that aren’t set. It accepts an array with the WooCommerce delivery method ID as the key and the Mailstep Courier ID as the value.
```php
apply_filters('kbnt_mailstep_fallback_couriers', []);
```
### Parameters
[Section titled “Parameters”](#parameters-2)
* **$fallback\_couriers** (array) WC method\_id → Mailstep courier\_id.
### Example usage
[Section titled “Example usage”](#example-usage)
```php
add_filter('kbnt_mailstep_fallback_couriers', function(){
return [
"local_pickup" => 123,
];
});
```
### Source code
[Section titled “Source code”](#source-code-2)
The filter is located in the file *includes/class-kbnt-mailstep-api.php*.
## kbnt\_mailstep\_get\_order\_courier\_id
[Section titled “kbnt\_mailstep\_get\_order\_courier\_id”](#kbnt_mailstep_get_order_courier_id)
Lets you modify the Courier ID.
```php
apply_filters('kbnt_mailstep_get_order_courier_id', get_option('wc_kbnt_mailstep_settings_shipping_' . $shipping_method->get_method_id() . ':' . $shipping_method->get_instance_id(), false), $order, $shipping_method->get_method_id(), $shipping_method->get_instance_id());
```
### Parameters
[Section titled “Parameters”](#parameters-3)
* **$courier\_id** (int) Courier ID (according to the Kybernaut Mailstep settings).
* **$order** (WC\_Order) The order.
* **$method\_id** (string) The delivery method ID.
* **$instance\_id** (string) The delivery method instance ID.
### Source code
[Section titled “Source code”](#source-code-3)
The filter is located in the file *includes/class-kbnt-mailstep-api.php*.
***
## kbnt\_mailstep\_order\_set
[Section titled “kbnt\_mailstep\_order\_set”](#kbnt_mailstep_order_set)
The filter returns the individual parameters sent to Mailstep and lets developers modify them.
```php
apply_filters('kbnt_mailstep_order_set', $parameters, $order);
```
### Parameters
[Section titled “Parameters”](#parameters-4)
* **$parameters** (array) The individual parameters sent to Mailstep.
* **$order** (WC\_Order) The order.
### Source code
[Section titled “Source code”](#source-code-4)
The filter is located in the file *includes/class-kbnt-mailstep-api.php*.
***
## kbnt\_mailstep\_sync\_excluded\_store\_ids
[Section titled “kbnt\_mailstep\_sync\_excluded\_store\_ids”](#kbnt_mailstep_sync_excluded_store_ids)
The filter lets you exclude warehouses from the Mailstep stock status synchronization. You can find the Store IDs either from Mailstep or in the log. **After a change, [clear the synchronization cache](/mailstep/stock-synchronization/#clearing-the-stock-synchronization-cache).**
```php
apply_filters('kbnt_mailstep_sync_excluded_store_ids', []);
```
### Parameters
[Section titled “Parameters”](#parameters-5)
* **$exluded\_store\_ids** (array) A list of warehouse IDs (string).
### Source code
[Section titled “Source code”](#source-code-5)
The filter is located in the file *includes/class-kbnt-mailstep-inventory-sync.php*.
***
## kbnt\_mailstep\_sync\_inventory\_products\_per\_sync
[Section titled “kbnt\_mailstep\_sync\_inventory\_products\_per\_sync”](#kbnt_mailstep_sync_inventory_products_per_sync)
The filter returns how many products are synchronized with the stock level in Mailstep at once.
```php
apply_filters('kbnt_mailstep_sync_inventory_products_per_sync', 300);
```
### Parameters
[Section titled “Parameters”](#parameters-6)
* **$products\_per\_sync** (int) The number of products synchronized at once.
### Source code
[Section titled “Source code”](#source-code-6)
The filter is located in the file *includes/class-kbnt-mailstep-inventory-sync.php*.
***
## kbnt\_mailstep\_sync\_inventory\_recurrence
[Section titled “kbnt\_mailstep\_sync\_inventory\_recurrence”](#kbnt_mailstep_sync_inventory_recurrence)
The filter lets you set how often the automatic stock synchronization runs. After a change, turn stock synchronization off and on again so it gets rescheduled.
```php
apply_filters('kbnt_mailstep_sync_inventory_recurrence', 'hourly');
```
### Parameters
[Section titled “Parameters”](#parameters-7)
* **$recurrence** (string) How often the event should subsequently repeat. You can find the permitted values in the [wp\_get\_schedules()](https://developer.wordpress.org/reference/functions/wp_get_schedules/) function.
### Source code
[Section titled “Source code”](#source-code-7)
The filter is located in the file *includes/class-kbnt-mailstep-inventory-sync.php*.
***
## kbnt\_mailstep\_sync\_only\_store\_id
[Section titled “kbnt\_mailstep\_sync\_only\_store\_id”](#kbnt_mailstep_sync_only_store_id)
The filter lets you select a single warehouse to be used for the Mailstep stock status synchronization. You can find the Store ID either from Mailstep or in the log. **After a change, [clear the synchronization cache](/mailstep/stock-synchronization/#clearing-the-stock-synchronization-cache).**
```php
apply_filters('kbnt_mailstep_sync_only_store_id', "")
```
### Parameters
[Section titled “Parameters”](#parameters-8)
* **$store\_id** (string) The warehouse ID.
### Source code
[Section titled “Source code”](#source-code-8)
The filter is located in the file *includes/class-kbnt-mailstep-inventory-sync.php*.
***
## kbnt\_mailstep\_unreleased\_stock\_order\_statuses
[Section titled “kbnt\_mailstep\_unreleased\_stock\_order\_statuses”](#kbnt_mailstep_unreleased_stock_order_statuses)
This setting lets you work with “blocked” stock, i.e. it adds goods not yet released by Mailstep to the shop’s stock level and thus prevents artificially inflating the stock. By default it contains “Pending payment” (Pending), “On hold” (On hold) and “Mailstep – Input error”, but you can adjust them this way. After adjusting, **you must [clear the stock cache](/mailstep/stock-synchronization/#clearing-the-stock-synchronization-cache)**.
```php
apply_filters('kbnt_mailstep_unreleased_stock_order_statuses', ['wc-pending', 'wc-inputerror', 'wc-on-hold']);
```
### Parameters
[Section titled “Parameters”](#parameters-9)
* **$statuses** (array) Order statuses
### Source code
[Section titled “Source code”](#source-code-9)
The filter is located in the file *includes/class-kbnt-mailstep-inventory-sync.php*.
***
## kbnt\_mailstep\_skip\_order\_item
[Section titled “kbnt\_mailstep\_skip\_order\_item”](#kbnt_mailstep_skip_order_item)
The filter lets you skip an order item (product) so that it isn’t sent to Mailstep. Return `true` to skip the given item. It’s used, for example, by the WooCommerce Product Bundles integration to omit the bundle’s parent product.
```php
apply_filters('kbnt_mailstep_skip_order_item', false, $product);
```
### Parameters
[Section titled “Parameters”](#parameters-10)
* **$skip** (bool) Whether to skip the item (default `false`).
* **$product** (WC\_Product) The order item’s product.
### Source code
[Section titled “Source code”](#source-code-10)
The filter is located in the file *includes/class-kbnt-mailstep-api.php*.
***
## kbnt\_mailstep\_api\_timeout
[Section titled “kbnt\_mailstep\_api\_timeout”](#kbnt_mailstep_api_timeout)
The filter sets the time limit (in seconds) for requests to the Mailstep API.
```php
apply_filters('kbnt_mailstep_api_timeout', 90);
```
### Parameters
[Section titled “Parameters”](#parameters-11)
* **$timeout** (int) The time limit in seconds (default `90`).
### Source code
[Section titled “Source code”](#source-code-11)
The filter is located in the file *includes/class-kbnt-mailstep-api.php*.
***
## kbnt\_mailstep\_get\_order\_id\_from\_order\_number
[Section titled “kbnt\_mailstep\_get\_order\_id\_from\_order\_number”](#kbnt_mailstep_get_order_id_from_order_number)
The filter lets you customize how a WooCommerce order ID is looked up from an order number in Mailstep – useful with custom order numbering.
```php
apply_filters('kbnt_mailstep_get_order_id_from_order_number', $order_id, $order_number);
```
### Parameters
[Section titled “Parameters”](#parameters-12)
* **$order\_id** (int|false) The looked-up order ID.
* **$order\_number** (string) The order number from Mailstep.
### Source code
[Section titled “Source code”](#source-code-12)
The filter is located in the file *includes/admin/wc-tools.php*.
***
## kbnt\_mailstep\_status\_lookback\_days
[Section titled “kbnt\_mailstep\_status\_lookback\_days”](#kbnt_mailstep_status_lookback_days)
The filter determines how many days back are searched when pulling order statuses from Mailstep (Mailstep only allows filtering by date). The default value is 30 days; the “Mailstep – force update order status” action is hidden for older orders.
```php
apply_filters('kbnt_mailstep_status_lookback_days', 30);
```
### Parameters
[Section titled “Parameters”](#parameters-13)
* **$days** (int) The number of days back (default `30`).
### Source code
[Section titled “Source code”](#source-code-13)
The filter is located in the file *kybernaut-mailstep.php*.
***
## kbnt\_mailstep\_allowed\_product\_statuses
[Section titled “kbnt\_mailstep\_allowed\_product\_statuses”](#kbnt_mailstep_allowed_product_statuses)
The filter returns the product statuses that are included in product queries (e.g. during stock synchronization).
```php
apply_filters('kbnt_mailstep_allowed_product_statuses', ['publish', 'draft', 'private']);
```
### Parameters
[Section titled “Parameters”](#parameters-14)
* **$statuses** (array) Product statuses (default `publish`, `draft`, `private`).
### Source code
[Section titled “Source code”](#source-code-14)
The filter is located in the file *includes/class-kbnt-mailstep-products.php*.
***
## kbnt\_mailstep\_order\_failed\_to\_send\_notification\_recipient
[Section titled “kbnt\_mailstep\_order\_failed\_to\_send\_notification\_recipient”](#kbnt_mailstep_order_failed_to_send_notification_recipient)
The filter returns the recipients of the admin e-mail notification that is sent when an order fails to be sent to Mailstep.
```php
apply_filters('kbnt_mailstep_order_failed_to_send_notification_recipient', [get_option('admin_email')]);
```
### Parameters
[Section titled “Parameters”](#parameters-15)
* **$recipients** (array) An array of e-mail addresses (default: the administrator’s e-mail).
### Source code
[Section titled “Source code”](#source-code-15)
The filter is located in the file *includes/add-order-status.php*.
***
## kbnt\_mailstep\_order\_statuses\_pairs
[Section titled “kbnt\_mailstep\_order\_statuses\_pairs”](#kbnt_mailstep_order_statuses_pairs)
The filter returns the mapping of numeric Mailstep statuses (0–14) to WooCommerce order status slugs.
```php
apply_filters('kbnt_mailstep_order_statuses_pairs', $statuses);
```
### Parameters
[Section titled “Parameters”](#parameters-16)
* **$statuses** (array) An array in the form Mailstep ID → WooCommerce status slug.
### Example usage
[Section titled “Example usage”](#example-usage-1)
```php
add_filter('kbnt_mailstep_order_statuses_pairs', function ($statuses) {
$keep_statuses = ['cancelled', 'refunded', 'completed', 'inputerror'];
foreach ($statuses as $key => $value) {
if (!in_array($value, $keep_statuses)) {
unset($statuses[$key]);
}
}
$statuses[4] = 'completed';
return $statuses;
});
```
### Source code
[Section titled “Source code”](#source-code-16)
The filter is located in the file *kybernaut-mailstep.php*.
***
## Actions for developers
[Section titled “Actions for developers”](#actions-for-developers)
**Actions (hooks)** – the following items let you attach your own code to the plugin’s events using `add_action()`.
***
## kbnt\_mailstep\_status\_get\_process\_order\_by\_order
[Section titled “kbnt\_mailstep\_status\_get\_process\_order\_by\_order”](#kbnt_mailstep_status_get_process_order_by_order)
The action runs for each order when pulling statuses from Mailstep and is the main extension point for processing an order status. By default, status mapping, handling of the intermediate “On the way” status, and blocking of order cancellation are hooked onto it (priorities 10/20/30).
```php
do_action('kbnt_mailstep_status_get_process_order_by_order', $order, $mailstep_status);
```
### Parameters
[Section titled “Parameters”](#parameters-17)
* **$order** (WC\_Order) The order.
* **$mailstep\_status** (stdClass) The status object from Mailstep.
### Example usage
[Section titled “Example usage”](#example-usage-2)
```php
add_action('kbnt_mailstep_status_get_process_order_by_order', function ($order, $mailstep_status) {
if ((int) $mailstep_status->status_id === 10) {
$order->add_order_note('Mailstep status 10 received.');
}
}, 40, 2);
```
### Source code
[Section titled “Source code”](#source-code-17)
The action is located in the file *kybernaut-mailstep.php*.
***
## kbnt\_mailstep\_add\_tracking\_id
[Section titled “kbnt\_mailstep\_add\_tracking\_id”](#kbnt_mailstep_add_tracking_id)
The action runs with the shipment’s tracking number (tracking ID) obtained from Mailstep, so you can work with it further – for example, save it to the order.
```php
do_action('kbnt_mailstep_add_tracking_id', $tracking_id, $order);
```
### Parameters
[Section titled “Parameters”](#parameters-18)
* **$tracking\_id** (string) The shipment’s tracking number from Mailstep.
* **$order** (WC\_Order) The order.
### Example usage
[Section titled “Example usage”](#example-usage-3)
```php
add_action('kbnt_mailstep_add_tracking_id', function ($tracking_id, $order) {
if (class_exists('WC_Shipment_Tracking_Api')) {
WC_Shipment_Tracking_Api::add_tracking_number($order->get_id(), $tracking_id, 'mailstep', current_time('mysql'), '');
}
}, 100, 2);
```
### Source code
[Section titled “Source code”](#source-code-18)
The action is located in the file *includes/class-kbnt-mailstep-orders.php*.
***
## kbnt\_mailstep\_inventory\_sync\_update\_product\_stock
[Section titled “kbnt\_mailstep\_inventory\_sync\_update\_product\_stock”](#kbnt_mailstep_inventory_sync_update_product_stock)
The action runs for each product during stock synchronization from Mailstep (after a stock change is detected).
```php
do_action('kbnt_mailstep_inventory_sync_update_product_stock', $product, $new_stock, $parent_id);
```
### Parameters
[Section titled “Parameters”](#parameters-19)
* **$product** (WC\_Product) The product (or variation).
* **$new\_stock** (int) The new stock level.
* **$parent\_id** (int|false) The parent product’s ID for variations, otherwise `false`.
### Example usage
[Section titled “Example usage”](#example-usage-4)
```php
add_action('kbnt_mailstep_inventory_sync_update_product_stock', function ($product, $new_stock, $parent_id) {
// Custom handling after a product stock update.
}, 10, 3);
```
### Source code
[Section titled “Source code”](#source-code-19)
The action is located in the file *includes/class-kbnt-mailstep-inventory-sync.php*.
***
## kbnt\_mailstep\_order\_failed\_to\_send
[Section titled “kbnt\_mailstep\_order\_failed\_to\_send”](#kbnt_mailstep_order_failed_to_send)
The action runs when an order fails to be sent to Mailstep (e.g. an API error or no response).
```php
do_action('kbnt_mailstep_order_failed_to_send', $order, $error_message);
```
### Parameters
[Section titled “Parameters”](#parameters-20)
* **$order** (WC\_Order) The order.
* **$error\_message** (string) A description of the error.
### Source code
[Section titled “Source code”](#source-code-20)
The action is located in the file *includes/class-kbnt-mailstep-api.php*.
# Logging
> How to enable logging of Mailstep requests and where to view the log in WooCommerce. Errors are always recorded; full logging is optional.
The plugin can record outgoing and incoming Mailstep requests. **A record is always saved whenever an error occurs**, or if you turn on error tracking.
## Enable logging of all requests
[Section titled “Enable logging of all requests”](#enable-logging-of-all-requests)
If you want to record all requests (for example during a fresh deployment of the plugin), go to the settings in **WooCommerce → Settings** under the **Mailstep** tab and tick **Enable logging.**

Enable error logging
## Viewing the log
[Section titled “Viewing the log”](#viewing-the-log)
You either click through to the record from the plugin settings via the “View log” link (see the image above), or via **WooCommerce → Status → Logs**, where you select the correct log (mailstep) with the correct date from the dropdown.

# Manual order status synchronization
> How to manually force Mailstep to pull all order statuses when an order gets stuck in a non-final state, using the Mailstep order action.
If an order has “got stuck” in a non-final status (completed, failed, refunded) and you want to manually force pulling **all** statuses from Mailstep, you can do so in the order detail by selecting **Order actions → Mailstep force update order status.**

# Resending an order to Mailstep
> How to resend an order to Mailstep after fixing an error that blocked sending, or when the integration was activated only after the order was created.
You’re probably asking this in one of two situations – an error occurred, you fixed it, and you need to send the order again, correctly (see the [first solution](/mailstep/resend-order/#the-order-should-have-been-sent-but-an-error-occurred)), or you activated sending later and need to send the orders to Mailstep retroactively. In that case, take a look at the [second solution](/mailstep/resend-order/#the-integration-was-activated-after-the-order-was-created).
## The order should have been sent, but an error occurred
[Section titled “The order should have been sent, but an error occurred”](#the-order-should-have-been-sent-but-an-error-occurred)
If sending to Mailstep fails, you’ll see a note in the order detail containing the order error, looking roughly like this:

An order not sent to Mailstep
You’ll be able to send such an order to Mailstep manually (after fixing the error) using the red button in the Order actions column:

Resending the order (red button on the right)
Note
If you don’t see the order actions column in the orders overview, you may first need to enable it in **Screen options** in the top right, see the image below

## The integration was activated after the order was created
[Section titled “The integration was activated after the order was created”](#the-integration-was-activated-after-the-order-was-created)
If you activated the Mailstep integration only after the order was created, you have to repeat the change to the status at which the order should be placed. You’ll find it in **WooCommerce → Settings → Mailstep**, roughly halfway down, in the **Send to Mailstep** setting.

The order status for sending to Mailstep
If this status is already active on the order, set a different one and then change it to the status for sending to Mailstep.
Danger
Bear in mind, though, that if you have **Processing** set there, WooCommerce sends an e-mail to the customer when the order enters it. If you set it a second time, it sends the e-mail a second time.
The problem described above has a fairly simple solution, however:
1. In the **Send to Mailstep** setting, choose the **Mailstep – Paid** option and save the settings. You most likely have no e-mail sending set up for this status.
2. In the orders overview, set this status on the orders you want to send to Mailstep – the orders are sent immediately.
3. Change the **Send to Mailstep** setting back to the status you had there before.
# Mailstep settings
> Configure the Mailstep plugin in WooCommerce: connect your account, pair shipping methods, choose order statuses, and activate the integration.
All plugin settings are configured in **WooCommerce → Settings** under the **Mailstep** tab. If you haven’t installed the plugin yet, you’ll want to start with the [Plugin installation](/general/plugin-installation/) article.

## Basic settings
[Section titled “Basic settings”](#basic-settings)
Below we’ll go through the individual plugin settings that need to be adjusted before you start using it. The other, optional parameters are covered in a separate part of the help below.
### 1. Connecting to Mailstep
[Section titled “1. Connecting to Mailstep”](#1-connecting-to-mailstep)
First, let’s prepare the testing username and password we received during Mailstep onboarding. Enter them in the **Username** and **Password** fields.
If you didn’t receive your own URLs for the individual endpoints during onboarding, leave them as they are (**Live endpoint URL**: , **Test endpoint URL**: ).
If the details you entered are correct, the borders of all fields turn green after a short validation. If any border is red, it can mean the following:
* **red username and password** – incorrect username and password (or the wrong endpoint attached to them, but unless you use some old endpoint, the default setting should work)
* **red Test endpoint URL** – the username and password work on the live site, but you don’t have the test endpoint enabled at Mailstep
* **red Live endpoint URL** – the username and password work on the test site, but the live endpoint isn’t enabled
To start, I recommend **[enabling logging](/mailstep/logging/)** of all requests to Mailstep so that, should you ever need to troubleshoot something, you know what’s happening in your shop. Once you’ve finished testing, you can disable logging. Failed requests that aren’t successfully added to Mailstep are logged either way.
Note
**Test mode** – use it if you’ve been given access to Mailstep’s test interface. If you don’t have it, run your tests on the live environment with an order you’ll reliably recognize – e.g. a sender named Test, and so on.
Danger
If you also sell in EUR, you need to contact Mailstep to have EUR enabled on their side (because of the conversion when insuring the parcel); nothing needs to be changed in the plugin.
### 2. Pairing shipping and delivery classes in Mailstep
[Section titled “2. Pairing shipping and delivery classes in Mailstep”](#2-pairing-shipping-and-delivery-classes-in-mailstep)
In this section you need to pair the individual shipping methods you have in WooCommerce (attached to the individual shipping zones) with the couriers you use in Mailstep.
For example, if you ship by courier, you’ll want to find the matching carrier such as PPL, Geis, InTime, DPD, GLS, DHL Connect, DHL Express and Liftago.
Danger
You’ll have to update this section whenever you add a new shipping method – if you happen to forget, sending to Mailstep will fail, but once you’ve fixed it you can [resend the order manually](/mailstep/resend-order/#the-order-should-have-been-sent-but-an-error-occurred).
### 3. Order statuses
[Section titled “3. Order statuses”](#3-order-statuses)
Now it remains to choose when the order is sent to Mailstep. The **Send to Mailstep** option applies only to orders that aren’t paid by cash on delivery – those are sent to Mailstep immediately.
Here you want to select the order status the order reaches after payment.
Note
It depends on your workflow – most often it will be the **Processing** status. But if you use it, for example, to send a fulfillment e-mail or in any other way, the plugin adds a new option, **Mailstep – Paid**, which has no customer e-mail sending attached to it.
Under **Cancel order** you set when a cancelled order should also be cancelled in Mailstep, so you don’t have to do it in two places. The default option is the standard **Cancelled** order status.
### 4. Activating the integration and testing
[Section titled “4. Activating the integration and testing”](#4-activating-the-integration-and-testing)
Once you have all the basic settings ready, go all the way back to the top of the settings and enable the integration by ticking **Enable integration**.
From this moment on, all orders are sent to Mailstep, where they are matched using the product’s **SKU** in WooCommerce against the product stored in Mailstep with the same value in its **Internal SKU** field.
Danger
If a product isn’t found by the **SKU** – **Internal SKU** combination, the order results in an error.
I recommend testing the entire order process so you know everything works correctly. If you need help with the setup, you can reach out to Mailstep or [me](/support/).
## Stock synchronization
[Section titled “Stock synchronization”](#stock-synchronization)
Stock synchronization has its [own article](/mailstep/stock-synchronization/), but in short – we can do it, just **read it carefully**.
## Additional settings
[Section titled “Additional settings”](#additional-settings)
Besides the settings mentioned above, the plugin offers several other options.
### Custom order statuses
[Section titled “Custom order statuses”](#custom-order-statuses)
If you run a large shop, it’s quite possible that in addition to the basic WooCommerce statuses you also use some others that your developer prepared for you or that you added via a plugin.
If you want to use your own status when an order is received into Mailstep (the **New order** status), you can select it in the **Mailstep “New order” status** option.
If you want to use a custom status for the moment the shipment is on its way (i.e. **Mailstep – Handed over to carrier**, or **Mailstep – Ready for pickup** in the case of personal pickup), you can use the **Mailstep “On the way” status** option.
If you want to hook your own actions onto other order statuses, your developer can do so the standard way, as if editing the default statuses. If you don’t have a developer, I’ll gladly help you with it – you can contact me [here](https://kybernaut.cz/kontakt).
### Hooks and filters for developers
[Section titled “Hooks and filters for developers”](#hooks-and-filters-for-developers)
If you need to change the plugin’s behavior in a way that isn’t described here, have your developer read the section with the [ready-made hooks and filters](/mailstep/developer-filters/) for further extending the plugin.
# Stock synchronization
> How to synchronize WooCommerce stock with Mailstep: manual and automatic modes, multiple warehouses, clearing the cache, and comparing stock levels.
Danger
You must have stock management [enabled and set up in WooCommerce](/mailstep/stock-synchronization/#stock-settings-in-woocommerce).
This way, Mailstep lets you synchronize **up to 10,000 products**. If you have more, a custom adjustment will be needed.
If you want to synchronize WooCommerce stock with the stock levels in Mailstep, please choose the mode that best suits your e-commerce model.
**By default, items from orders not yet handed over to Mailstep are deducted from the stock received from Mailstep**, i.e. those in the stock statuses Pending payment, On hold and Mailstep – Input error (you can adjust this with a [filter](/mailstep/developer-filters/#kbnt_mailstep_unreleased_stock_order_statuses)). In the settings you can see the number of such orders and click through to view them.
If you have [multiple warehouses](/mailstep/stock-synchronization/#multiple-warehouses-in-mailstep) defined in Mailstep, their levels are added together in WooCommerce.

## Manual
[Section titled “Manual”](#manual)
**You have everything under control and update the stock at the press of a button whenever you stock new goods.** The synchronization is scheduled and runs on its own the next time pages are viewed.
A suitable choice if stock levels don’t decrease in any way other than through sales in the e-shop (you don’t have a branch, another e-shop, etc.).
## Automatic
[Section titled “Automatic”](#automatic)
**The stock changes frequently because you also sell at a branch, and so on.**
The stock is synchronized once an hour\* (depending on site traffic, or rather on the behavior of the WordPress cron, which runs once the time limit has elapsed during a page visit).
Note
The first synchronization can take quite a while – with the standard setting, the plugin updates only 300 products at a time. If you have more, it schedules another 300 a minute later so as not to overload your site. If you’re confident about your server configuration, [you can increase the number](/mailstep/developer-filters/#kbnt_mailstep_sync_inventory_products_per_sync).
Subsequent synchronizations should already be faster, because only what has changed since the previous synchronization is updated.
Danger
With ordinary use of payment methods that have no “delay” – such as card payment, instant transfer or cash on delivery – there shouldn’t be any stock discrepancies.
If you use custom order statuses (or plugins that have them) in which the goods haven’t yet been handed over to Mailstep, make sure you have them set as statuses that reduce the stock; if not, use the [filter](/mailstep/developer-filters/#kbnt_mailstep_unreleased_stock_order_statuses).
If you still need to use automatic stock synchronization, one solution may be to update the stock, say, just once a day (after payments have been credited to your account), or, for example, to have a stock update programmed to run after new goods are received in Mailstep.
Your developer can help set how often it runs by using [this filter](/mailstep/developer-filters/#kbnt_mailstep_sync_inventory_recurrence) or by calling the `kbnt_mailstep_sync_inventory_manuall_hook` action, which schedules a one-off cron run (like pressing the button above).
For further code adjustments, [contact me](https://kybernaut.cz/kontakt).
## Multiple warehouses in Mailstep
[Section titled “Multiple warehouses in Mailstep”](#multiple-warehouses-in-mailstep)
If you have more than one warehouse created in Mailstep (which is fairly rare), by default the plugin works with the sum of their stock levels for a given product (SKU).
Using filters, you (or your developer) can set whether goods are loaded only from [a single warehouse](/mailstep/developer-filters/#kbnt_mailstep_sync_only_store_id) or, conversely, [exclude certain warehouses](/mailstep/developer-filters/#kbnt_mailstep_sync_excluded_store_ids) from synchronization (and the rest will continue to be summed).
You can see information about the currently used setting in the Mailstep plugin administration as *Synchronized warehouses.*

## Clearing the stock synchronization cache
[Section titled “Clearing the stock synchronization cache”](#clearing-the-stock-synchronization-cache)
If you need to clear the stock synchronization cache, i.e. you want to update everything from scratch (rather than updating only the difference between the last stock and the new one) or you need to restart the whole process, you can do so at the press of a button.
You’ll find it in **WooCommerce → Status → Tools** under the name **Clear the Mailstep stock status synchronization cache**.

## Comparing stock in Mailstep and WooCommerce
[Section titled “Comparing stock in Mailstep and WooCommerce”](#comparing-stock-in-mailstep-and-woocommerce)
If you want to verify that everything is transferred correctly from Mailstep to WooCommerce (without running the synchronization itself), you can run a check and look at the log. If the levels of products present in both warehouses differ, you’ll find the information in the log.
The listing also takes into account items not yet released that aren’t in Mailstep (“Pending payment” (Pending), “On hold” (On hold) and “Mailstep – Input error” (which you can optionally adjust with a filter [see the documentation](/mailstep/developer-filters/#kbnt_mailstep_unreleased_stock_order_statuses)).
You’ll find it in **WooCommerce → Status → Tools** under the name **Get information about stock synchronization with Mailstep**.

Running the tool via **WooCommerce → Status → Tools**
You’ll find the results in the Mailstep log (regardless of whether you normally log everything or not) under the Logs tab (see [How to view the log](/mailstep/logging/#viewing-the-log)).

An example of a log where not everything is synchronized (WC in-stock count + unsent order statuses)

Stock status OK, but one product doesn’t have stock quantity synchronization enabled (only in stock / out of stock)

Everything is currently synchronized
## Stock settings in WooCommerce
[Section titled “Stock settings in WooCommerce”](#stock-settings-in-woocommerce)
For the synchronization to work correctly, you must of course have stock enabled in WooCommerce, which you can check in **WooCommerce → Settings → Products → Inventory.**

At this point, WooCommerce handles a product’s stock status with the **In stock** and **Out of stock** flags. If you want to manage product quantities in stock, you need to enable **Stock management at product level** for each product.

For more detailed information about stock behavior in WooCommerce, see the article by Vláďa Musílek [here](https://musilda.cz/nastaveni-skladu-ve-woocommerce/). For bulk editing you can use, for example, the [WooCommerce Stock Manager](https://wordpress.org/plugins/woocommerce-stock-manager/) plugin.
# Uninstalling and deactivating the plugin
> What happens to Mailstep order statuses when you deactivate or uninstall the plugin, and how to handle order statuses and customer e-mails safely.
You can of course deactivate and uninstall the plugin in the completely usual way, but keep in mind that when the plugin isn’t active, WooCommerce won’t recognize the custom order statuses added by the plugin (these statuses start with “Mailstep – ”).
On deactivation, orders with an unknown status disappear from the orders listing (but remain in the database) and reappear once you reactivate the plugin.
If you deactivate the plugin, orders with these statuses are automatically changed to “Processing”, but the customer is no longer sent an e-mail notification. If you want to adjust this default behavior, you can do so in the plugin settings (WooCommerce → Settings → Mailstep → the Uninstall section).
You can of course also resolve the situation manually by editing the order statuses in WooCommerce before deactivating the plugin.
Danger
Watch out for re-sending an e-mail from WooCommerce – if the user already received such an e-mail during the purchase process, you probably don’t want to send it to them again (in that case, the way to do it is to disable its sending in WooCommerce → Settings → E-mails and the settings of the selected e-mail, and turn it back on after changing the status).
Alternatively, I explain everything in the video below:

# Kybernaut Messenger
> Send WooCommerce orders to the Messenger courier service and schedule pickups directly from your store admin.
**Kybernaut Messenger** connects your WooCommerce store to the [Messenger](https://www.messenger.cz/) courier service. Orders are handed over to the courier automatically, including cash-on-delivery details.
## Start here
[Section titled “Start here”](#start-here)
1. [Before you start](/messenger/before-you-start/)
2. [Plugin installation](/general/plugin-installation/)
3. [Plugin settings](/messenger/settings/)
## Useful links
[Section titled “Useful links”](#useful-links)
* [Plugin page & pricing](https://kybernaut.cz/en/plugins/kybernaut-messenger/)
* [Changelog](https://kybernaut.cz/en/plugins/kybernaut-messenger/changelog-kybernaut-messenger/)
* [Get support](/support/)
# Before you start
> What to request from Messenger before connecting the plugin — credentials, test access, tracking webhook registration, and a ready-to-send e-mail.
Before the plugin can talk to Messenger, you need a few things from them. It’s easiest to ask for everything in one e-mail — there’s a ready-to-copy template at the end of this page.
## What you need from Messenger
[Section titled “What you need from Messenger”](#what-you-need-from-messenger)
| What | Where it goes in the plugin | Note |
| :------------------- | :-------------------------- | :------------------------------------------------------------------------------------------------------------------- |
| Customer number | *Zákaznické číslo* | numeric, used for API authentication |
| Password | *Heslo* | used for API authentication |
| importKey | *importKey* | issued by Messenger’s IT department |
| Shipping type number | *Typ přepravy* | the default 106 = Over Economy (delivery the day after pickup); other types by agreement with their sales department |
All of these are entered under **WooCommerce → Settings → Shipping → Messenger** — see [Plugin settings](/messenger/settings/).
## Test access
[Section titled “Test access”](#test-access)
The plugin ships with **test mode enabled by default**, so nothing reaches the production environment right after installation. Test mode talks to `api-test.messenger.cz`, and you can check your test shipments in the [test portal](https://portal-test.messenger.cz/portal/login).
Ask Messenger for **separate test credentials** — production credentials don’t work against the test environment. Once you’ve verified everything works, don’t forget to turn test mode off.
## Tracking webhook registration
[Section titled “Tracking webhook registration”](#tracking-webhook-registration)
To have order statuses update automatically (including the switch to *Completed* after delivery), Messenger needs to know where to send shipment status updates. Give them the URL the plugin shows at the top of its settings page:
```plaintext
https://YOUR-DOMAIN/wp-json/kbnt-messenger/v1/trackingstates/
```
Format: JSON, method: POST. Without this registration the statuses won’t update and orders won’t move to *Completed* on their own — more in [Order statuses](/messenger/order-statuses/).
## One more thing to mention
[Section titled “One more thing to mention”](#one-more-thing-to-mention)
The plugin sends the **house number together with the street** in a single field (there is no separate house-number field). Let Messenger know so their side parses addresses correctly — the plugin reminds you about this in its settings, too.
## Ready-to-send e-mail template
[Section titled “Ready-to-send e-mail template”](#ready-to-send-e-mail-template)
```text
Subject: WooCommerce integration — access request
Hello,
we are connecting our e-shop (https://YOUR-DOMAIN) to your API via the
Kybernaut Messenger WooCommerce plugin. Please send us:
1. Customer number, password, and importKey for the production API.
2. Test credentials for api-test.messenger.cz, so we can verify the
integration first.
3. Our agreed shipping type number (if different from 106 / Over Economy).
Please also register our tracking-states webhook:
URL: https://YOUR-DOMAIN/wp-json/kbnt-messenger/v1/trackingstates/
Format: JSON, method POST.
Note: our system sends the house number together with the street in one
field.
Thank you!
```
# Developer filters and actions
> Reference of the Kybernaut Messenger plugin's WordPress filters and actions for customizing package weight, cash on delivery, order data, and tracking.
If you can’t find a filter or action you need here, [contact me](/support/) with where and how you’d like it added, and I’ll be glad to do so, so that future plugin updates stay safe.
## kbnt\_messenger\_cod\_methods
[Section titled “kbnt\_messenger\_cod\_methods”](#kbnt_messenger_cod_methods)
The filter returns the slugs of payment methods that are treated as cash on delivery.
```php
apply_filters('kbnt_messenger_cod_methods', ['cod', 'dobirka']);
```
### Parameters
[Section titled “Parameters”](#parameters)
* **$methods** (array) Slugs of the payment methods treated as cash on delivery.
### Source code
[Section titled “Source code”](#source-code)
The filter is located in the file *classes/WooCommerce/Order.php*.
***
## kbnt\_messenger\_max\_package\_weight
[Section titled “kbnt\_messenger\_max\_package\_weight”](#kbnt_messenger_max_package_weight)
Adjusts the maximum weight of an individual package.
```php
apply_filters('kbnt_messenger_max_package_weight', $weight, $order);
```
### Parameters
[Section titled “Parameters”](#parameters-1)
* **$weight** (int) The maximum package weight in kilograms.
* **$order** (WC\_Order) The order.
### Source code
[Section titled “Source code”](#source-code-1)
The filter is located in the file *classes/WooCommerce/Order.php*.
***
## kbnt\_messenger\_max\_package\_weight\_cart
[Section titled “kbnt\_messenger\_max\_package\_weight\_cart”](#kbnt_messenger_max_package_weight_cart)
The cart-calculation variant of `kbnt_messenger_max_package_weight` — adjusts the maximum weight of an individual package when the package count is calculated from the cart.
```php
apply_filters('kbnt_messenger_max_package_weight_cart', $weight, $cart);
```
### Parameters
[Section titled “Parameters”](#parameters-2)
* **$weight** (int) The maximum package weight in kilograms.
* **$cart** (WC\_Cart) The cart.
### Source code
[Section titled “Source code”](#source-code-2)
The filter is located in the file *classes/WooCommerce/Cart.php*.
***
## kbnt\_messenger\_max\_send\_attempts
[Section titled “kbnt\_messenger\_max\_send\_attempts”](#kbnt_messenger_max_send_attempts)
Adjusts how many times the plugin automatically retries sending an order to Messenger before it gives up (a note is then added to the order; the manual “Resend to Messenger” button resets the counter).
```php
apply_filters('kbnt_messenger_max_send_attempts', 3);
```
### Parameters
[Section titled “Parameters”](#parameters-3)
* **$max\_attempts** (int) The maximum number of automatic send attempts. Default 3.
### Source code
[Section titled “Source code”](#source-code-3)
The filter is located in the file *inc/order-to-messenger.php*.\
Available since version 2.6.2.
***
## kbnt\_messenger\_order\_data
[Section titled “kbnt\_messenger\_order\_data”](#kbnt_messenger_order_data)
The filter returns the individual parameters sent to Messenger and lets developers modify them.
```php
apply_filters('kbnt_messenger_order_data', $data, $order);
```
### Parameters
[Section titled “Parameters”](#parameters-4)
* **$data** (array) The individual parameters sent to Messenger. More information in the [Messenger API](https://portal.messenger.cz/dev/api/importer#tech-spec-nepovinne-parametry) documentation.
* **$order** (WC\_Order) The order.
### Source code
[Section titled “Source code”](#source-code-4)
The filter is located in the file *classes/WooCommerce/Order.php*.
***
## kbnt\_messenger\_order\_to\_messenger\_failure
[Section titled “kbnt\_messenger\_order\_to\_messenger\_failure”](#kbnt_messenger_order_to_messenger_failure)
Action fired when an order fails to be sent to the Messenger system.
```php
do_action('kbnt_messenger_order_to_messenger_failure', $order, $imported);
```
### Parameters
[Section titled “Parameters”](#parameters-5)
* **$order** (WC\_Order) The order.
* **$imported** (stdClass) Messenger’s response regarding the sent order.
### Source code
[Section titled “Source code”](#source-code-5)
The action is located in the file *inc/order-to-messenger.php*.
***
## kbnt\_messenger\_order\_to\_messenger\_success
[Section titled “kbnt\_messenger\_order\_to\_messenger\_success”](#kbnt_messenger_order_to_messenger_success)
Action fired when an order is successfully sent to the Messenger system.
```php
do_action('kbnt_messenger_order_to_messenger_success', $order, $imported);
```
### Parameters
[Section titled “Parameters”](#parameters-6)
* **$order** (WC\_Order) The order.
* **$imported** (stdClass) Messenger’s response regarding the sent order.
### Source code
[Section titled “Source code”](#source-code-6)
The action is located in the file *inc/order-to-messenger.php*.
***
## kbnt\_messenger\_package\_weight
[Section titled “kbnt\_messenger\_package\_weight”](#kbnt_messenger_package_weight)
Adjusts the weight of the packaging material.
```php
apply_filters('kbnt_messenger_package_weight', $weight, $order);
```
### Parameters
[Section titled “Parameters”](#parameters-7)
* **$weight** (float) The weight of the packaging material.
* **$order** (WC\_Order) The order.
### Source code
[Section titled “Source code”](#source-code-7)
The filter is located in the file *classes/WooCommerce/Order.php*.
***
## kbnt\_messenger\_package\_weight\_cart
[Section titled “kbnt\_messenger\_package\_weight\_cart”](#kbnt_messenger_package_weight_cart)
The cart-calculation variant of `kbnt_messenger_package_weight` — adjusts the weight of the packaging material when the package count is calculated from the cart.
```php
apply_filters('kbnt_messenger_package_weight_cart', $weight, $cart);
```
### Parameters
[Section titled “Parameters”](#parameters-8)
* **$weight** (float) The weight of the packaging material.
* **$cart** (WC\_Cart) The cart.
### Source code
[Section titled “Source code”](#source-code-8)
The filter is located in the file *classes/WooCommerce/Cart.php*.
***
## kbnt\_messenger\_pcs\_per\_package
[Section titled “kbnt\_messenger\_pcs\_per\_package”](#kbnt_messenger_pcs_per_package)
Adjusts the number of products packed in each package.
```php
apply_filters('kbnt_messenger_pcs_per_package', $pcs, $order);
```
### Parameters
[Section titled “Parameters”](#parameters-9)
* **$pcs** (int) The number of products in a single package.
* **$order** (WC\_Order) The order.
### Source code
[Section titled “Source code”](#source-code-9)
The filter is located in the file *classes/WooCommerce/Order.php*.
***
## kbnt\_messenger\_pcs\_per\_package\_cart
[Section titled “kbnt\_messenger\_pcs\_per\_package\_cart”](#kbnt_messenger_pcs_per_package_cart)
The cart-calculation variant of `kbnt_messenger_pcs_per_package` — adjusts the number of products packed in each package when the package count is calculated from the cart.
```php
apply_filters('kbnt_messenger_pcs_per_package_cart', $pcs, $cart);
```
### Parameters
[Section titled “Parameters”](#parameters-10)
* **$pcs** (int) The number of products in a single package.
* **$cart** (WC\_Cart) The cart.
### Source code
[Section titled “Source code”](#source-code-10)
The filter is located in the file *classes/WooCommerce/Cart.php*.
***
## kbnt\_messenger\_send\_error\_notifications\_active
[Section titled “kbnt\_messenger\_send\_error\_notifications\_active”](#kbnt_messenger_send_error_notifications_active)
Disables notifications about failed sends to Messenger.
```php
apply_filters('kbnt_messenger_send_error_notifications_active', $send_notification);
```
### Parameters
[Section titled “Parameters”](#parameters-11)
* **$send\_notification** (bool) Should the notification e-mail be sent?
### Source code
[Section titled “Source code”](#source-code-11)
The filter is located in the file *classes\Logger\Logger.php*.
***
## kbnt\_messenger\_send\_error\_notifications\_to
[Section titled “kbnt\_messenger\_send\_error\_notifications\_to”](#kbnt_messenger_send_error_notifications_to)
Changes the recipient of the notification e-mail (default: the site admin).
```php
apply_filters('kbnt_messenger_send_error_notifications_to', $to);
```
### Parameters
[Section titled “Parameters”](#parameters-12)
* **$to** (array) The recipients’ e-mail addresses.
### Source code
[Section titled “Source code”](#source-code-12)
The filter is located in the file *classes\Logger\Logger.php*.
***
## kbnt\_messenger\_send\_other\_shipping\_methods
[Section titled “kbnt\_messenger\_send\_other\_shipping\_methods”](#kbnt_messenger_send_other_shipping_methods)
Lets you pass an array of `shipping method IDs` (e.g. *flat\_rate*) or strings `{shipping method ID}:{shipping method instance ID}` (e.g. *flat\_rate:1*) for which orders will also be sent to Messenger.
If you don’t know the ID, you can find it on the Checkout by looking at the code, as [I show in the video tutorial](https://www.loom.com/share/59a6915de55442a89f105f4d6337fca5?sid=0bf1b05c-c565-415f-ae19-9c63e47587c8).
```php
apply_filters('kbnt_messenger_send_other_shipping_methods', $other_methods);
```
### Example
[Section titled “Example”](#example)
```php
add_filter('kbnt_messenger_send_other_shipping_methods', function() {
return ['free_shipping', 'flat_rate:2'];
});
```
### Parameters
[Section titled “Parameters”](#parameters-13)
* **$other\_methods** (array) `shipping method IDs` (e.g. *flat\_rate*) or strings `{shipping method ID}:{shipping method instance ID}` (e.g. *flat\_rate:1*) for which orders will also be sent to Messenger.
### Source code
[Section titled “Source code”](#source-code-13)
The filter is located in the file *inc/order-to-messenger.php*.\
Available since version 2.1.0.
***
## kbnt\_messenger\_trackingstates
[Section titled “kbnt\_messenger\_trackingstates”](#kbnt_messenger_trackingstates)
```php
do_action('kbnt_messenger_trackingstates', $order, $data);
```
### Parameters
[Section titled “Parameters”](#parameters-14)
* **$order** (WC\_Order) The order.
* **$data** (array) Shipment data from [Messenger](https://portal.messenger.cz/dev/api/trackingstates#successful-result).
### Source code
[Section titled “Source code”](#source-code-14)
The action is located in the file *inc\endpoints.php*.
***
## kbnt\_messenger\_trackingstates\_order\_not\_found
[Section titled “kbnt\_messenger\_trackingstates\_order\_not\_found”](#kbnt_messenger_trackingstates_order_not_found)
```php
do_action('kbnt_messenger_trackingstates', $data);
```
### Parameters
[Section titled “Parameters”](#parameters-15)
* **$data** (array) Shipment data from [Messenger](https://portal.messenger.cz/dev/api/trackingstates#successful-result).
### Source code
[Section titled “Source code”](#source-code-15)
The action is located in the file *inc\endpoints.php*.
***
## kbnt\_messenger\_variable\_symbol\_cod
[Section titled “kbnt\_messenger\_variable\_symbol\_cod”](#kbnt_messenger_variable_symbol_cod)
Changes the variable symbol for cash-on-delivery payment.
```php
apply_filters('kbnt_messenger_variable_symbol_cod', $order_id, $order);
```
### Parameters
[Section titled “Parameters”](#parameters-16)
* **$order\_id** (int) The order number.
* **$order** (WC\_Order) The order.
### Source code
[Section titled “Source code”](#source-code-16)
The filter is located in the file *inc\order-to-messenger.php*.
***
## Order meta keys
[Section titled “Order meta keys”](#order-meta-keys)
After a successful handover to Messenger, the plugin stores the tracking data in order meta — handy for custom snippets and integrations:
* **\_kbnt\_messenger\_order\_id** — Messenger’s shipment ID.
* **\_kbnt\_messenger\_tracking\_code** — the tracking code.
* **\_kbnt\_messenger\_tracking\_url** — the tracking URL.
Read them with `$order->get_meta('_kbnt_messenger_tracking_url')` etc. An example e-mail snippet is in the [FAQ](/messenger/faq/).
# Frequently asked questions
> Answers to common pre-sale and support questions about the Kybernaut Messenger plugin — Age Check, tracking in e-mails, invoicing plugins, WooPayments.
Questions I get asked repeatedly — verified against the plugin code and the Messenger API documentation.
## Does the plugin support age verification (18+ / Age Check)?
[Section titled “Does the plugin support age verification (18+ / Age Check)?”](#does-the-plugin-support-age-verification-18--age-check)
Age Check is a **Messenger-side service**, not an API parameter — the Messenger import API has no field for it, so there is nothing the plugin could send. If you have Age Check active on your contract for all shipments, you don’t need to configure anything in the plugin.
The one thing to check with Messenger: whether they tie Age Check to a specific **shipping type number**. If so, enter that number under **WooCommerce → Settings → Shipping → Messenger → Typ přepravy**. Note that the shipping type is a **global setting** — it applies to all Messenger shipping instances, not per shipping zone.
If Messenger ever needs an extra field in the shipment data, the [`kbnt_messenger_order_data`](/messenger/developer-filters/#kbnt_messenger_order_data) filter lets you add any parameter to the API payload — globally or conditionally (e.g. only for orders containing alcohol).
## How do I get the tracking number into a customer e-mail?
[Section titled “How do I get the tracking number into a customer e-mail?”](#how-do-i-get-the-tracking-number-into-a-customer-e-mail)
The plugin shows the tracking link on the order detail in the admin, but does **not** add it to customer e-mails by itself. Two things to know first:
* The **“Completed order” e-mail is sent only after delivery** (see [Order status lifecycle](/messenger/order-statuses/)), so a tracking link there arrives too late to be useful.
* Messenger notifies the recipient anyway — an **SMS with a delivery window** on the delivery day, and since plugin version 2.7.0 they also receive the customer’s e-mail address. A tracking link from the e-shop is a nice-to-have, not a necessity.
If you want it anyway, the tracking data is stored in order meta, so a small snippet does the job — it prints the link into any customer e-mail generated after the order was handed to Messenger:
```php
add_action('woocommerce_email_before_order_table', function ($order, $sent_to_admin, $plain_text, $email) {
// Only for customer e-mails and orders already handed to Messenger.
if ($sent_to_admin || ! $order->get_meta('_kbnt_messenger_tracking_url')) {
return;
}
printf(
'Track your shipment: %s
',
esc_url($order->get_meta('_kbnt_messenger_tracking_url')),
esc_html($order->get_meta('_kbnt_messenger_tracking_code'))
);
}, 10, 4);
```
## Is the plugin compatible with invoicing plugins and WooPayments?
[Section titled “Is the plugin compatible with invoicing plugins and WooPayments?”](#is-the-plugin-compatible-with-invoicing-plugins-and-woopayments)
There is no direct conflict — the plugin doesn’t touch payment gateways or invoicing. What you do need to account for is the [order status lifecycle](/messenger/order-statuses/):
* **WooPayments** (and other gateways) work as expected: a successful payment sets *Processing*, which is exactly what triggers the handover to Messenger. Card payments are correctly not treated as cash on delivery.
* **Invoicing plugins** (Toret Fakturoid and others): bind invoice creation to the **Processing** status. Anything bound to *Completed* fires only after delivery — often days later.
* Integrations that check whether an order **is paid** work correctly from plugin version 2.7.0, which registers the *Messenger* status among WooCommerce’s paid statuses.
The general rule: anything that reacts to *Completed* behaves differently with this plugin than in a vanilla WooCommerce shop, because *Completed* means *delivered*.
## How does the plugin split orders into packages?
[Section titled “How does the plugin split orders into packages?”](#how-does-the-plugin-split-orders-into-packages)
See the dedicated page: [Package splitting](/messenger/package-splitting/). The short version: items-per-package first, weight as a safety cap, and every product needs a weight set in WooCommerce.
# Manually sending an order to Messenger
> Manually resend a WooCommerce order to Messenger when automatic sending didn't happen — for backorder, failed, and processing orders.
## What is the order resend feature?
[Section titled “What is the order resend feature?”](#what-is-the-order-resend-feature)
Since version 2.6.0 of the Kybernaut Messenger plugin, you can manually send an order to the Messenger system even when automatic sending didn’t happen. This feature is especially useful in the following situations:
* **Orders with backorder products** – these orders aren’t sent automatically and wait for you to send them manually
* **Orders with the “Failed” status** – if a previous send attempt failed
* **Orders with the “Processing” status** – that haven’t yet been sent to Messenger for some other reason (e.g. when created manually in the admin)
## When does the resend button appear?
[Section titled “When does the resend button appear?”](#when-does-the-resend-button-appear)
The “Resend to Messenger” button (an icon with a refresh symbol) appears automatically on orders that meet the following conditions:
1. **Shipping method used:** The order must have the Messenger shipping method set (or another allowed shipping method added via the `kbnt_messenger_send_other_shipping_methods` filter)
2. **Order status:** The order must be in one of these statuses:
* **Processing**
* **Failed**
* **On hold** – typically for backorder products
3. **Not yet sent:** The order must not have already been successfully sent to Messenger (it has no assigned Messenger ID)
## Backorder products
[Section titled “Backorder products”](#backorder-products)
Since version 2.6.0, the plugin automatically detects orders containing backorder products and **does not send them to Messenger automatically**. This lets you wait until the products are back in stock and then send the order manually.
### How does the plugin detect backorder products?
[Section titled “How does the plugin detect backorder products?”](#how-does-the-plugin-detect-backorder-products)
The plugin recognizes a backorder product in these cases:
1. The product’s stock status is explicitly set to “On backorder” (onbackorder)
2. The WooCommerce `is_on_backorder()` method returns `true`
3. The product allows backorders and the ordered quantity exceeds the available stock
When an order with backorder products is detected, the plugin:
* Automatically adds a note to the order: *“Order contains backorder products. Not automatically sent to Messenger. Use ‘Resend to Messenger’ when ready.”*
* Does not send the order to Messenger automatically
* Shows the button for manual sending
## How to manually send an order
[Section titled “How to manually send an order”](#how-to-manually-send-an-order)
There are two ways to manually send an order to Messenger:
### From the orders list
[Section titled “From the orders list”](#from-the-orders-list)
1. Go to **WooCommerce → Orders**
2. Find the order you want to send
3. In the **Order actions** column (on the right) there is an icon with a red resend button
4. Click the red icon with the rotation (refresh) symbol
5. The order is sent to Messenger immediately

### From the order detail
[Section titled “From the order detail”](#from-the-order-detail)
1. Open the order detail (click the order number)
2. In the right-hand **Order actions** panel, find the dropdown menu
3. Select **“Resend to Messenger”**
4. Click the **“Apply”** button (the arrow)
5. The order is sent to Messenger

## What happens during a manual send?
[Section titled “What happens during a manual send?”](#what-happens-during-a-manual-send)
When you manually send an order:
1. **Send to the Messenger API:** The plugin sends the order data (recipient, packages, cash on delivery, etc.) to the Messenger system
2. **Order note:** A note is automatically added: *“Order manually resent to Messenger.”*
3. **Saving tracking information:** After a successful send, the following are saved:
* The order’s Messenger ID (`_kbnt_messenger_order_id`)
* Tracking number (`_kbnt_messenger_tracking_code`)
* Shipment tracking URL (`_kbnt_messenger_tracking_url`)
4. **Status change:** The order changes status to **“Messenger”** (if the send succeeds) or **“Failed”** (if the send fails)
5. **Displaying tracking information:** In the order detail, below the delivery address, the Messenger ID and a shipment tracking link are shown
## Troubleshooting
[Section titled “Troubleshooting”](#troubleshooting)
### The button doesn’t appear
[Section titled “The button doesn’t appear”](#the-button-doesnt-appear)
Check whether:
* The order has the correct shipping method set (Messenger)
* The order has the correct status (Processing, Failed, or On hold)
* The order hasn’t already been successfully sent (it has no Messenger ID)
* The Kybernaut Messenger plugin is active and correctly configured
### Sending fails
[Section titled “Sending fails”](#sending-fails)
1. **Check the API credentials:**
* WooCommerce → Settings → Shipping → Messenger
* Verify the Username, Password, and Import Key
1. **Check the test mode:**
* Make sure you have the right credentials for the test or production environment
1. **Enable debug mode:**
* In the Messenger settings, enable “Debug mode”
* Try sending the order again
* Check the logs: WooCommerce → Status → Logs (look for files starting with “messenger-”)
### An order with backorder products was sent automatically
[Section titled “An order with backorder products was sent automatically”](#an-order-with-backorder-products-was-sent-automatically)
This behavior is unexpected as of version 2.6.0. Check:
* Are you using plugin version 2.6.0 or newer?
* Is the product actually set to “On backorder” in the inventory settings?
* Check the debug logs for more information
## For developers
[Section titled “For developers”](#for-developers)
If you want to enable manual sending for other shipping methods too, you first need to [hook them into sending to Messenger using a filter](/messenger/developer-filters/#kbnt_messenger_send_other_shipping_methods).
# Order status lifecycle
> How a WooCommerce order moves through statuses with Messenger — Processing, Messenger, Completed, Failed — and which customer e-mails go out when.
Understanding the order lifecycle saves a lot of head-scratching — especially around customer e-mails and invoicing integrations, which often assume the standard WooCommerce flow. With this plugin the flow looks like this:
## The lifecycle
[Section titled “The lifecycle”](#the-lifecycle)
1. **Processing** — the customer has paid (or placed a cash-on-delivery order). This status is the trigger: the plugin sends the order to the Messenger API.
2. **Messenger** — the order was successfully handed over to Messenger. This is the plugin’s own custom status. Since version 2.7.0 it **counts as a paid status**, so revenue reports and integrations that check `$order->is_paid()` treat it correctly.
3. **Completed** — set automatically when Messenger reports the shipment as *delivered* (via the tracking webhook). Not before.
4. **Failed** — set when sending to the Messenger API fails, or when Messenger reports the shipment as permanently undeliverable.
Statuses in between (courier assigned, picked up, delivery attempt failed…) don’t change the order status — they are added as **order notes**, so the whole journey is visible on the order detail.
## The tracking webhook is what moves the status
[Section titled “The tracking webhook is what moves the status”](#the-tracking-webhook-is-what-moves-the-status)
Steps 3 and 4 only happen if Messenger has your tracking webhook registered — the URL shown at the top of the plugin settings (`/wp-json/kbnt-messenger/v1/trackingstates/`). Without it, orders stay in the *Messenger* status forever. See [Before you start](/messenger/before-you-start/#tracking-webhook-registration).
## What this means for customer e-mails
[Section titled “What this means for customer e-mails”](#what-this-means-for-customer-e-mails)
* WooCommerce sends **no e-mail** for the custom *Messenger* status — the customer isn’t notified when the parcel is handed to the courier.
* The **“Completed order” e-mail goes out only after delivery** — so putting a tracking link in that template makes little sense; the parcel is already in the customer’s hands.
* Messenger notifies the recipient on its own: on the delivery day they send an **SMS with a time window** and the courier’s phone number (using the phone the plugin passes along). Since version 2.7.0 the plugin also passes the customer’s **e-mail address** to Messenger.
If you still want the tracking link in an e-mail, see [the FAQ](/messenger/faq/#how-do-i-get-the-tracking-number-into-a-customer-e-mail) for a ready-made snippet.
## What this means for invoicing and other integrations
[Section titled “What this means for invoicing and other integrations”](#what-this-means-for-invoicing-and-other-integrations)
Anything that reacts to *Completed* fires **after delivery** — often days after payment. For invoicing plugins (Toret Fakturoid and similar), I recommend binding invoice creation to the **Processing** status instead. Integrations that check whether the order is *paid* work correctly from version 2.7.0 onward, since the *Messenger* status is registered among the paid statuses. More in [the FAQ](/messenger/faq/#is-the-plugin-compatible-with-invoicing-plugins-and-woopayments).
## Where the tracking data lives
[Section titled “Where the tracking data lives”](#where-the-tracking-data-lives)
After a successful handover, the plugin shows the Messenger ID and a tracking link on the order detail in the admin, and stores them in order meta:
| Meta key | Content |
| :------------------------------ | :---------------------- |
| `_kbnt_messenger_order_id` | Messenger’s shipment ID |
| `_kbnt_messenger_tracking_code` | tracking code |
| `_kbnt_messenger_tracking_url` | tracking URL |
These are handy for snippets and custom integrations — see [Developer filters and actions](/messenger/developer-filters/).
# Package splitting
> How the Messenger plugin splits an order into packages — item count first, weight as a safety cap — with a worked example and the filters to fine-tune it.
The plugin splits every order into one or more packages automatically. The logic is driven by three settings under **WooCommerce → Settings → Shipping → Messenger**:
| Setting | Meaning | Default |
| :----------------- | :------------------------------------------- | :------ |
| *Ks do balíku* | how many items fit into one package | 9999 |
| *Obalový materiál* | weight of the packaging material per package | 0.25 kg |
| *Max. hmotnost* | maximum weight of a single package | 30 kg |
## The algorithm — items first, weight as a cap
[Section titled “The algorithm — items first, weight as a cap”](#the-algorithm--items-first-weight-as-a-cap)
1. The package count starts from the **item count**: `packages = ceil(items ÷ items per package)`.
2. Then a **weight check**: if an average package (order weight ÷ packages, plus packaging material) would exceed the maximum weight, the package count is increased so no package goes over the limit.
3. Each package is reported to Messenger with the **average weight** (total weight incl. packaging ÷ package count), rounded **up to whole kilograms** — that’s what the Messenger API expects.
So the main lever is the item count; weight only kicks in as a safety cap for heavy orders.
## Worked example: wine in six-packs
[Section titled “Worked example: wine in six-packs”](#worked-example-wine-in-six-packs)
A winery ships bottles (1.5 kg each) in cartons of six, so *Ks do balíku* = 6 and packaging weight 0.25 kg:
| Order | Packages | Reported weight |
| :------------------ | :------- | :-------------------------------- |
| 6 bottles (9 kg) | 1 | 10 kg (9 + 0.25, rounded up) |
| 7 bottles (10.5 kg) | 2 | 6 kg each (11 ÷ 2, rounded up) |
| 12 bottles (18 kg) | 2 | 10 kg each (18.5 ÷ 2, rounded up) |
Note the 7-bottle case: Messenger receives two packages with the **same average weight**, even though you’ll physically pack 6 + 1.
## Things to know
[Section titled “Things to know”](#things-to-know)
* **Every product must have a weight set** in WooCommerce (**Product data → Shipping**), otherwise the weight cap can never do its job. See also [Plugin settings](/messenger/settings/#adding-product-weight-in-woocommerce).
* The plugin does **not** send Messenger’s size category (`velikost`), nor package dimensions — Messenger determines the size category on their side. No plugin setting influences it.
* Since version 2.7.0 the default packaging weight (0.25 kg) is applied consistently in the cart and on the order, and an explicitly set zero is respected.
## Fine-tuning with filters
[Section titled “Fine-tuning with filters”](#fine-tuning-with-filters)
For per-order or per-cart logic you can override the three inputs with filters — `kbnt_messenger_pcs_per_package`, `kbnt_messenger_package_weight`, and `kbnt_messenger_max_package_weight` (plus their `_cart` variants used during cart calculations). See [Developer filters and actions](/messenger/developer-filters/).
# Messenger settings
> Configure the Kybernaut Messenger WooCommerce plugin: credentials, shipping type, package weight, cash on delivery, and delivery status tracking.
You configure the Messenger integration under **WooCommerce → Settings** on the **Shipping → Messenger** tab. You adjust the shipping price the usual way through **WooCommerce → Settings → Shipping**, just as you’re used to. If you haven’t installed the plugin yet, you’ll want to start with the [Plugin installation](/general/plugin-installation/) article.

## Basic settings
[Section titled “Basic settings”](#basic-settings)
Below we’ll go through the individual plugin settings in **WooCommerce → Settings → Shipping → Messenger** that you need to adjust before you start using it.
### 1. Integration
[Section titled “1. Integration”](#1-integration)
1. Enter your **username** and **password** (the same ones you use to log in to the Messenger portal).
2. Enter the **importKey**, which you should receive from Messenger. If you don’t have it, contact [their support](https://www.messenger.cz/kontakty/praha.html).
3. To start, I recommend enabling **debug logging**, which stores every request sent to Messenger so you know what’s happening in your shop. Once you’ve finished testing, you can turn logging off. Requests that Messenger rejects outright as invalid are logged either way.
Most errors (missing data and the like) won’t be logged, because Messenger doesn’t process requests in real time. If such an error does happen, they usually give you a call, so there’s no need to worry.
### 2. Shipping settings
[Section titled “2. Shipping settings”](#2-shipping-settings)
Set the **shipping type** – unless you’ve arranged a special one, leave it as type 106 (economy delivery, the day after pickup). The number is how Messenger distinguishes the products and services agreed on your contract (for example a shipping type with the Age Check service). Keep in mind it’s a **global setting** — it applies to every Messenger shipping instance, not per shipping zone.
For Messenger to work correctly, the plugin has to pass the number of packages and their weight rounded to whole kilograms. Because with multiple packages WooCommerce can’t guess how you’ll want to pack the shipment, I agreed with Messenger that the total weight of all packages will be divided across their number (i.e. it doesn’t reflect the actual packing), but it should be enough for adjusting the price.
The shipment weight is calculated from the product weights ([how to add a product’s weight?](/messenger/settings/#adding-product-weight-in-woocommerce)) plus the weight of the packaging material. You can enter that in the **Packaging material weight** setting.
You can influence how many packages the goods are split into in two ways (whichever condition is met first applies):
* **Items per package** – the number of pieces in a single package (useful e.g. when shipping bottles of wine and the like).
* **Maximum package weight** – if you have lots of small items that are better packed together, you’ll probably want to set a maximum package weight and a very high number of items per package (e.g. shipping cosmetics).
If you need to change these values for specific cases, you can use the [available filters](/messenger/developer-filters/), which your developer will surely handle.
### 3. Pickup location
[Section titled “3. Pickup location”](#3-pickup-location)
In this section, enter the details of who will send the packages on your behalf and where they can be picked up.
### 4. Activation, adding the shipping method, and a test
[Section titled “4. Activation, adding the shipping method, and a test”](#4-activation-adding-the-shipping-method-and-a-test)
Once all the basic settings are ready, go back to the very top of the settings and enable the integration by ticking **Enable – Send orders to Messenger**.
Now it’s time to set up the Messenger shipping method:
1. On the **WooCommerce → Settings → Shipping** tab, in your shipping zones choose the zone in which you want to ship goods via Messenger.
2. Click the **Add shipping method** button and select **Messenger**.
3. Set the price and a custom name for the shipping method.
Once that’s set up, you can send a test order to Messenger, which you’ll find in the [test portal](https://portal-test.messenger.cz/portal/login) on the **Shipment overview → All shipments** tab.
The order is sent when it reaches the **Processing** status, i.e. after payment has been entered.
Note
Unfortunately, Messenger doesn’t guarantee the availability of the test portal – if the shipment doesn’t show up there, contact their support. They’ll help you out.
Danger
Careful – when sending an order to Messenger, use a real street, city, and postal code in the delivery address – orders with non-existent details won’t reach Messenger at all.
If you need to test in live operation, instead of a made-up address use the first name and last name fields, and possibly the order note.
If everything is in order, you can turn off test mode.
## Cash on delivery
[Section titled “Cash on delivery”](#cash-on-delivery)
The plugin automatically handles passing the cash-on-delivery amount for the standard “Cash on delivery” (COD) payment and for the Cash on delivery method added by WooCommerce Shipping. If you need another payment method to be treated as cash on delivery, you’ll need to adjust it with a [filter](/messenger/developer-filters/#kbnt_messenger_cod_methods); if you’re not sure how, [write to me](/support/).
## Tracking delivery status
[Section titled “Tracking delivery status”](#tracking-delivery-status)
If you want to track an order’s delivery status in the admin, you need to send Messenger the address of your REST API that will process the shipment statuses. You’ll find it under **WooCommerce → Settings → Shipping → Messenger**:

With each status change, a new note is added to the order. On delivery, the order status then changes to **Completed**.
## Adding product weight in WooCommerce
[Section titled “Adding product weight in WooCommerce”](#adding-product-weight-in-woocommerce)
For everything to work correctly, every product you offer must have its weight set, which you can verify under **WooCommerce → Settings → Products → Inventory**.
You can set it in the product detail under **Product data → Shipping**.

Setting the weight in the product detail.
Alternatively, on the **Products** list you can use **Quick Edit**, or even the **Edit** bulk action if you have several products that weigh the same.

Adding or editing a product’s weight from the **Quick Edit** menu on the products list.
# Get support
> How to reach support for Kybernaut premium and free WordPress plugins, and what to prepare so your issue gets solved quickly.
## Before you write
[Section titled “Before you write”](#before-you-write)
Most questions are already answered here in the docs — try the search (`Ctrl`/`Cmd` + `K`) first. If something is broken, the [Health Check debugging guide](/general/health-check-debugging/) and [logging](/mailstep/logging/) usually reveal the cause.
## Premium plugins (Mailstep, Messenger)
[Section titled “Premium plugins (Mailstep, Messenger)”](#premium-plugins-mailstep-messenger)
Support for premium plugins is included in your subscription:
* **From your WordPress admin** — every premium plugin adds a **Contact Us** item under its menu, which sends me your message together with basic environment info (WordPress and plugin versions).
* **From your Freemius account** — log in to the [Freemius User Dashboard](https://users.freemius.com/) and use the support option next to your license. See [Your user account](/account/user-account/).
Please include your order/license ID, what you expected to happen, and what happened instead — screenshots help a lot.
### Or email me directly
[Section titled “Or email me directly”](#or-email-me-directly)
Write to **** and include:
* Which plugin — Mailstep or Messenger
* Plugin version
* WordPress version
* The website the issue is on
* What’s happening — a description of the problem, or an error log/screenshot
## Free plugins
[Section titled “Free plugins”](#free-plugins)
Support for free plugins happens in their WordPress.org forums, which I check about once a week in my free time:
[Kybernaut IČO DIČ](https://wordpress.org/support/plugin/woolab-ic-dic/)
[Pay for Payment for WooCommerce](https://wordpress.org/support/plugin/woocommerce-pay-for-payment/)
[Add Anchor Links](https://wordpress.org/support/plugin/add-anchor-links/)
[Simple Admin Language Change](https://wordpress.org/support/plugin/simple-admin-language-change/)
[Zalomení](https://wordpress.org/support/plugin/zalomeni/)
[Form Enhancer for Fluent Forms](https://wordpress.org/support/plugin/formenhancer/)
## Custom work
[Section titled “Custom work”](#custom-work)
Interested in a paid plugin customization or a tailored integration? [Contact me directly](https://kybernaut.cz/en/get-in-touch/).