

Status tab on a Master store, showing role, last inbound/outbound timestamps, the last outbound error, and a per-store Connection Health table with status, last activity, and remote WooCommerce/plugin versions for each connected Child.
Kitgenix Stock Sync for WooCommerce synchronizes inventory between WooCommerce stores using a Master/Child architecture. The Master store acts as the authoritative inventory source while Child stores send stock-changing events back to the Master and receive the resulting authoritative stock state.
The plugin is built for merchants who sell the same physical inventory through several WooCommerce storefronts and need stock quantity, stock status and backorder behaviour to converge without manually exporting/importing inventory files.
Stores communicate directly over signed REST requests; there is no Kitgenix cloud stock relay. Background delivery uses WooCommerce Action Scheduler where available, with retries and backlog handling for temporary failures.
Learn more about Kitgenix at Kitgenix.
The Master owns the authoritative stock state. A Child store can detect a local event that changes stock, send that event to the Master, and then receive the authoritative result that should be applied across the network.
This avoids a simple “last store to save wins” design in which two storefronts can continually overwrite one another with stale quantities.
The Master configuration stores the connected Child sites and the Child configuration stores the Master endpoint/credentials needed for signed communication.
The state payload includes the stock-related fields needed to keep WooCommerce availability consistent, including quantity, status, backorders, low-stock amount and effective manage-stock state.
Variable products/variations are handled with awareness that a variation may manage its own stock or inherit stock management from the parent product.
The plugin focuses on stock. It is not a general product-catalogue synchronizer for descriptions, images, categories and full pricing; Kitgenix MultiStore Sync is a separate broader plugin for that use case.
The sync engine hooks into WooCommerce product/variation stock updates, stock-status updates, updated product properties, order processing and stock restoration. This means stock changes made by normal WooCommerce operations can enter the sync pipeline without staff having to click a separate “export stock” button.
Because third-party integrations such as POS or marketplace connectors often write stock through WooCommerce’s normal APIs/hooks, their resulting WooCommerce stock changes can also be observed without the Kitgenix plugin calling the third party directly.
Each synchronized product carries plugin metadata used for global identity and event versioning. The receiver tracks the applied version so an older delayed event can be rejected instead of rolling stock backwards after a newer update has already been applied.
Event IDs are also remembered for a limited period so a duplicated/retried delivery is not applied as though it were a brand-new inventory movement.
Outbound failures are classified and retried using increasing delays. Recoverable failures can be persisted in a capped backlog so administrators can see that inventory delivery is pending rather than assuming a silent request succeeded.
Backlog entries can be retried or discarded from the administrative tools when appropriate. Successful later delivery removes the corresponding outstanding item.
The Master can scan Child stores and compare their current stock state with the authoritative record. Reconciliation processes products in batches and can continue through Action Scheduler rather than requiring a single long-running browser request.
Conflict reports can identify mismatched stock or duplicate-SKU conditions that need manual attention. The plugin also exposes audit/reconciliation functionality through WP-CLI.
A Child store can optionally validate cart quantities against the Master during checkout. This is intended to reduce overselling when the local storefront’s last synchronized value is older than the authoritative stock.
Because the Master can be temporarily unreachable, the plugin includes configurable behaviour around failure and stale cached stock snapshots. Stores should choose a strategy that matches whether they prefer checkout availability or strict oversell prevention during network outages.
The plugin observes SKU metadata changes so identity can remain consistent when a product’s SKU is edited. Global plugin IDs provide another stable identifier used by the sync process, reducing dependence on the assumption that a SKU can never change.
Administrators can exclude specific SKUs from stock synchronization. Excluded products are ignored by normal event delivery and reconciliation so local-only inventory is not continually overwritten.
Master and Child REST requests are signed using the shared-secret authentication layer. Requests include timing/identity information and are rejected when they are invalid, too large, outside the accepted window or fail replay/authentication checks.
The security layer also contains throttling/temporary lockout behaviour for repeated authentication failures and remote URL validation.
Shared secrets can be rotated with a configured overlap period so a network can move from an old secret to a new one without requiring every in-flight request to fail at the exact rotation second.
Scheduled health pings update the stored connection status for the Master/Child relationship. The admin interface and Site Health integration can report configuration, connectivity, backlog and Action Scheduler concerns.
The command base is:
wp kitgenix-stock-sync
The command class includes status, audit/reconciliation, SKU-level actions, backlog/conflict tooling and formatting helpers for operational use from the command line.
Stock events and stock-state queries are sent only between the WooCommerce sites configured by the administrator. Kitgenix does not receive the store’s inventory feed or act as a remote source of truth.
The shared Kitgenix admin Hub can separately request public plugin metadata from WordPress.org, and the admin stylesheet imports Google Fonts as documented in External Services. Those requests do not contain WooCommerce stock payloads.
This is a store-to-store sync plugin, so connecting to remote services is core to how it works. It talks to two kinds of external endpoint:
1. Your own WooCommerce stores (Master and Child)
The plugin makes signed REST API requests directly between the WordPress/WooCommerce sites you configure as Master and Child – it does not route data through any Kitgenix server or third-party service. Master and Child URLs must use HTTPS (a filter allows plain http:// only for localhost/.local/.test hosts for local development).
/ping health-check route, the sending store’s name and its WooCommerce/plugin version. Strict checkout validation additionally sends the SKUs currently in a Child’s cart to the Master for a live stock check.X-Kitgenix-Store-Id, X-Kitgenix-Timestamp, X-Kitgenix-Nonce, and an X-Kitgenix-Signature HMAC-SHA256 header computed from a shared secret you configure on both sides – see Developer Reference below for the full scheme.2. WordPress.org Plugins API (admin screen only, not part of stock sync)
The plugin includes a shared “Kitgenix hub” admin page (Kitgenix top-level menu) listing other Kitgenix plugins. To populate install counts, ratings, and artwork for plugins listed there, it calls WordPress core’s own plugins_api() function, which requests public plugin metadata from api.wordpress.org. No site data, settings, or stock information is sent in these requests – only the public plugin slugs of the Kitgenix plugins shown on that page.
kitgenix_hub_wporg_active_installs_v1, kitgenix_hub_wporg_ratings_v1, kitgenix_hub_wporg_media_v1 (24 hours each).No other third-party services, SaaS platforms, or analytics/tracking endpoints are contacted by this plugin.
Text domain:
kitgenix-stock-sync-for-woocommerce
Option key:
* kitgenix_stock_sync_for_woocommerce_settings
Option schema (high-level):
* this_store_id, this_store_name, role, strict_checkout_validation, schema_version
* checkout_validation_failure_strategy (fail_open | fail_closed | stale_cache), checkout_stale_cache_minutes
* master (child config): url, store_id, secret, secret_previous, secret_previous_expires_at, health
* children (master config): entries with id, name, url, secret, secret_previous, secret_previous_expires_at, enabled, health
* exclusions.skus
* conflicts_report: {generated_at, items[]} – each item has type, sku, gid, child_id, child_name, master_value, child_value, detail
* Diagnostics/admin UI state: notices, event_log, backlog (v2: id, type, store_id, attempt, status, next_retry_at, payload, payload_meta, error, code), reconcile (v2: mode, dry_run, differences_only, selected_skus, processed, total_estimate, differences_found, pushed_count, started_at, finished_at, last_batch_at), health (this store’s own global health, retained alongside the newer per-store master/children[].health)
Product/variation meta keys:
* _kitgenix_stock_sync_for_woocommerce_gid – stable cross-store identity, survives SKU renames. Never regenerated once set.
* _kitgenix_stock_sync_for_woocommerce_version – Master-authoritative monotonic version counter, bumped on every authoritative capture.
* _kitgenix_stock_sync_for_woocommerce_applied_version – last version a receiving store actually applied; the staleness-fencing guard.
REST API routes (POST):
* /wp-json/kitgenix-stock-sync/v1/ping – returns wc_version and plugin_version
* /wp-json/kitgenix-stock-sync/v1/event
* /wp-json/kitgenix-stock-sync/v1/stock (master only; used by strict checkout validation)
* /wp-json/kitgenix-stock-sync/v1/stock-state (used by audit/reconcile/conflict comparisons; returns gid and effective manage_stock)
All four routes register with permission_callback => __return_true and perform authentication inside the callback via the signed-request headers below – this is intentional (a signed server-to-server webhook has no WordPress user/cookie/application-password to authenticate against) and not a missing-permission-callback oversight.
Authentication headers:
* X-Kitgenix-Store-Id
* X-Kitgenix-Timestamp
* X-Kitgenix-Nonce
* X-Kitgenix-Signature
Signatures:
* HMAC SHA-256 over: timestamp + "\n" + nonce + "\n" + request_body
* Timing-safe comparison (hash_equals)
* Timestamp skew allowed: 5 minutes
* Nonce replay protection stored via transients; a nonce is only consumed once a request is confirmed authentic, so a wrong signature can’t burn a legitimate nonce slot
* Verification tries the current secret, then a rotated-out previous secret if it hasn’t expired (see “Rotate Secret”)
* Request bodies over 2MB are rejected before any HMAC work
* Repeated authentication failures from the same sender trigger a temporary lockout (20 failures / 10 minutes 15 minute lockout)
* All authentication failure responses are a single generic 401 (detailed reason logged internally only) so a caller cannot enumerate which store IDs are configured
Action Scheduler hooks:
* (Action group: kitgenix-stock-sync)
* kitgenix_stock_sync_for_woocommerce_process_event
* kitgenix_stock_sync_for_woocommerce_push_to_store – used for both the initial async dispatch (attempt 1) and scheduled retries of the same delivery (attempt > 1)
* kitgenix_stock_sync_for_woocommerce_send_to_master – same dual purpose, Child Master direction
* kitgenix_stock_sync_for_woocommerce_reconcile_batch
* kitgenix_stock_sync_for_woocommerce_process_order_processing
* kitgenix_stock_sync_for_woocommerce_health_ping – recurring, ~15 minutes
Admin capability:
* manage_woocommerce
Admin nonces:
* kss_save_config
* kss_save_connection
* kss_save_children
* kss_test_connection
* kss_tools
* kss_conflicts
* kss_logs
Filters:
* kitgenix_stock_sync_for_woocommerce_parent_menu_slug (change the parent menu slug; default: kitgenix)
* kitgenix_stock_sync_for_woocommerce_secret_rotation_overlap (seconds a rotated-out secret keeps working; default 86400, clamped to 1 hour–7 days)
* kitgenix_stock_sync_for_woocommerce_allow_insecure_url (return true to allow http:// for localhost/.local/.test hosts only – never for a real remote host)
Transients (dynamic keys):
* kitgenix_stock_sync_for_woocommerce_do_activation_redirect (30 seconds)
* kitgenix_stock_sync_for_woocommerce_kss_nonce_{md5(store_id|nonce)} (nonce replay protection, 10 minutes)
* kitgenix_stock_sync_for_woocommerce_kss_seen_{md5(event_id)} (duplicate event detection, 24 hours)
* kitgenix_stock_sync_for_woocommerce_kss_debounce_{md5(key)} (debounce, ~2 seconds)
* kitgenix_stock_sync_for_woocommerce_kss_old_sku_{post_id} (SKU rename helper, 60 seconds)
* kitgenix_stock_sync_for_woocommerce_kss_audit_result_{user_id} (stores last audit result in wp-admin, 10 minutes)
* kitgenix_stock_sync_for_woocommerce_kss_stockcache_{md5(sku)} (last-known-good stock snapshot for the stale_cache checkout strategy, 24 hours; a per-item cached_at timestamp – not the transient TTL – enforces the merchant-configured max age)
* kitgenix_stock_sync_for_woocommerce_kss_authfail_{md5(identity)} / ..._kss_lockout_{md5(identity)} (brute-force throttle)
Object cache (if persistent object cache is enabled):
* Cache group: kitgenix_stock_sync
* Key: kitgenix_stock_sync_for_woocommerce_kss_gid_{md5(gid)} (GID product ID lookup, ~1 hour)
Internal action hooks (called directly, but can be hooked):
* kitgenix_stock_sync_for_woocommerce_process_order_processing
wp kitgenix-stock-sync status [--format=<table|json|yaml>]
Role, store ID, and a per-store connection health summary.
wp kitgenix-stock-sync audit --skus=<a,b,c> [--format=<table|json>]
Master only. Compare Master vs. every configured Child for the given SKUs.
wp kitgenix-stock-sync reconcile [--skus=<a,b,c>] [--dry-run] [--differences-only] [--batch=<n>]
Master only. Runs to completion synchronously (with a progress bar) rather than relying on Action Scheduler’s own timing, so the command reports a real result. Omit --skus to reconcile the whole catalogue.
wp kitgenix-stock-sync sku push <sku>...
Master only. Push specific SKUs to all children immediately.
wp kitgenix-stock-sync backlog list|retry <id>|discard <id>|retry-all|discard-all [--yes]
Inspect and manage the backlog. discard/discard-all prompt for confirmation unless --yes is passed.
wp kitgenix-stock-sync conflicts [--rescan] [--format=<table|json>]
Print the current Conflict Dashboard report; --rescan runs a fresh duplicate-SKU scan first (Master only).
.local/.test hosts can opt into http:// for local development only, via a filter).kitgenix_stock_sync_for_woocommerce_settings), the same way most WordPress integrations store API credentials. Treat secrets like passwords. Secrets are never written to the Event Log, the Backlog, or WooCommerce’s own logs.This plugin removes its settings and plugin-only transients on uninstall. It does not remove WooCommerce product/order meta or Action Scheduler records – this is intentional …