{"id":327500,"date":"2026-07-17T19:28:48","date_gmt":"2026-07-17T19:28:48","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/2khat\/"},"modified":"2026-09-20T15:21:16","modified_gmt":"2026-09-20T15:21:16","slug":"2khat-catalog-sync","status":"publish","type":"plugin","link":"https:\/\/pt-ao.wordpress.org\/plugins\/2khat-catalog-sync\/","author":23517840,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.0.9","stable_tag":"1.0.9","tested":"7.0.6","requires":"5.0","requires_php":"7.4","requires_plugins":null,"header_name":"2khat Catalog Sync","header_author":"2khat","header_description":"Official WooCommerce catalog sync plugin for the 2khat platform.","assets_banners_color":"","last_updated":"2026-09-20 15:21:16","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"","header_author_uri":"https:\/\/2khat.com","rating":0,"author_block_rating":0,"active_installs":0,"downloads":335,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","changelog"],"tags":{"1.0.6":{"tag":"1.0.6","author":"mohammad61","date":"2026-07-17 19:28:27","revision":3611961},"1.0.7":{"tag":"1.0.7","author":"mohammad61","date":"2026-08-10 14:02:45","revision":3640691},"1.0.8":{"tag":"1.0.8","author":"mohammad61","date":"2026-08-10 16:10:35","revision":3640855},"1.0.9":{"tag":"1.0.9","author":"mohammad61","date":"2026-09-20 15:21:16","revision":3704382}},"upgrade_notice":[],"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3611961,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3611961,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":[],"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.0.6","1.0.7","1.0.8","1.0.9"],"block_files":[],"assets_screenshots":[],"screenshots":[]},"plugin_section":[],"plugin_tags":[],"plugin_category":[],"plugin_contributors":[272081],"plugin_business_model":[],"class_list":["post-327500","plugin","type-plugin","status-publish","hentry","plugin_contributors-mohammad61","plugin_committers-mohammad61"],"banners":[],"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/2khat-catalog-sync\/assets\/icon-128x128.png?rev=3611961","icon_2x":"https:\/\/ps.w.org\/2khat-catalog-sync\/assets\/icon-256x256.png?rev=3611961","generated":false},"screenshots":[],"raw_content":"<!--section=description-->\n<p>2khat connects your WooCommerce store to the 2khat platform by exposing a secure, paginated REST API for product catalog synchronization.<\/p>\n\n<p>After registering your store with the 2khat team, install and activate this plugin to allow 2khat to fetch your published products and variations.<\/p>\n\n<h3>Security<\/h3>\n\n<pre><code>public_key.pem is the 2khat RSA public key used to verify API request signatures. It is not a private credential and must remain in the plugin directory.&lt;h3&gt;Authentication&lt;\/h3&gt;\n<\/code><\/pre>\n\n<p>All 2khat API requests require RSA domain signature verification.<\/p>\n\n<p><strong>Signing (2khat server side):<\/strong><\/p>\n\n<ol>\n<li>Normalize the store domain: use the host from <code>site_url()<\/code>, without a <code>www.<\/code> prefix.<\/li>\n<li>Sign the domain string with the 2khat private key using SHA256.<\/li>\n<li>Base64-encode the binary signature.<\/li>\n<li><p>Send it in the request header:<\/p>\n\n<p>Authorization: Twokcs <\/p><\/li>\n<\/ol>\n\n<p>Legacy clients may also use <code>Authorization: Basic &lt;base64-signature&gt;<\/code> during migration.<\/p>\n\n<p><strong>Example (OpenSSL CLI):<\/strong><\/p>\n\n<pre><code>`\n<\/code><\/pre>\n\n<p>echo -n \"example.com\" | openssl dgst -sha256 -sign 2khat_private.pem | openssl base64 -A\n    <code>&lt;h3&gt;REST API&lt;\/h3&gt;\n**GET**<\/code>\/wp-json\/twokcs\/v1\/version`<\/p>\n\n<p>Returns the plugin version.<\/p>\n\n<p><strong>GET<\/strong> <code>\/wp-json\/twokcs\/v1\/products?page=1&amp;per_page=100<\/code><\/p>\n\n<p>Returns paginated published products with nested variations.<\/p>\n\n<p><strong>GET<\/strong> <code>\/wp-json\/twokcs\/v1\/categories?page=1&amp;per_page=100<\/code><\/p>\n\n<p>Returns paginated product categories.<\/p>\n\n<p><strong>GET<\/strong> <code>\/wp-json\/twokcs\/v1\/attributes?page=1&amp;per_page=100<\/code><\/p>\n\n<p>Returns paginated product attributes.<\/p>\n\n<p><strong>GET<\/strong> <code>\/wp-json\/twokcs\/v1\/attribute-terms?page=1&amp;per_page=100<\/code><\/p>\n\n<p>Returns paginated attribute terms across all attributes. Optionally filter by attribute:<\/p>\n\n<p><strong>GET<\/strong> <code>\/wp-json\/twokcs\/v1\/attribute-terms?attribute_id=1&amp;page=1&amp;per_page=100<\/code><\/p>\n\n<p><strong>GET<\/strong> <code>\/wp-json\/twokcs\/v1\/variants?product_ids=10,20<\/code><\/p>\n\n<p>Returns compact published variants grouped by parent product ID. Each item includes parent product fields (<code>product_id<\/code>, <code>type<\/code>, <code>manage_stock<\/code>, <code>price<\/code>, <code>regular_price<\/code>, <code>sale_price<\/code>, <code>stock_quantity<\/code>, <code>stock_status<\/code>) and a <code>variants<\/code> array with: <code>id<\/code>, <code>on_sale<\/code>, <code>status<\/code>, <code>price<\/code>, <code>regular_price<\/code>, <code>sale_price<\/code>, <code>stock_quantity<\/code>, <code>stock_status<\/code>. Simple products return an empty <code>variants<\/code> array and their own price\/stock on the parent object.<\/p>\n\n<p><strong>GET<\/strong> <code>\/wp-json\/twokcs\/v1\/variants?ids=305,306,307<\/code><\/p>\n\n<p>Returns compact published variants for the given variation IDs in request order. Response shape: <code>{ count, results: [...] }<\/code> with the same variant fields as above.<\/p>\n\n<p><strong>GET<\/strong> <code>\/wp-json\/twokcs\/v1\/variant?id=305<\/code><\/p>\n\n<p>Returns a single compact published variant object with the same fields as above. Returns 404 when the variation is missing or not published.<\/p>\n\n<p><strong>POST<\/strong> <code>\/wp-json\/twokcs\/v1\/orders<\/code><\/p>\n\n<p>Creates a WooCommerce order for the 2khat platform.<\/p>\n\n<p>Request body (JSON):<\/p>\n\n<ul>\n<li><code>external_order_id<\/code> (required) \u2014 platform order id, stored as <code>_twokcs_external_order_id<\/code><\/li>\n<li><code>line_items<\/code> (required) \u2014 array of <code>{ product_id, variation_id?, quantity }<\/code><\/li>\n<li><code>billing<\/code> \/ <code>shipping<\/code> \u2014 address objects<\/li>\n<li><code>status<\/code> \u2014 WooCommerce status without <code>wc-<\/code> prefix (default: <code>processing<\/code>)<\/li>\n<li><code>customer_note<\/code> \u2014 optional note<\/li>\n<li><code>meta_data<\/code> \u2014 optional array of <code>{ key, value }<\/code> (public keys and <code>_twokcs_*<\/code> only)<\/li>\n<\/ul>\n\n<p>Returns <strong>201<\/strong> with a compact order object. Duplicate <code>external_order_id<\/code> returns <strong>409<\/strong> with <code>existing_order_id<\/code>.<\/p>\n\n<p><strong>GET<\/strong> <code>\/wp-json\/twokcs\/v1\/order<\/code><\/p>\n\n<p>Lists orders as <code>{ count, max_pages, results }<\/code>. All filters are optional and combinable: <code>id<\/code>, <code>external_order_id<\/code>, <code>status<\/code>, plus <code>page<\/code> \/ <code>per_page<\/code>. Bare <code>GET \/order<\/code> returns a paginated list. No matches return an empty <code>results<\/code> array (200). If both <code>id<\/code> and <code>external_order_id<\/code> are provided and refer to different orders, the request returns 400.<\/p>\n\n<p>Examples:<\/p>\n\n<ul>\n<li><code>\/wp-json\/twokcs\/v1\/order<\/code><\/li>\n<li><code>\/wp-json\/twokcs\/v1\/order?status=processing<\/code><\/li>\n<li><code>\/wp-json\/twokcs\/v1\/order?id=123<\/code><\/li>\n<li><code>\/wp-json\/twokcs\/v1\/order?external_order_id=2khat-12345<\/code><\/li>\n<li><code>\/wp-json\/twokcs\/v1\/order?id=123&amp;status=processing<\/code><\/li>\n<\/ul>\n\n<p>Each result includes: <code>id<\/code>, <code>status<\/code>, <code>external_order_id<\/code>, <code>tracking_code<\/code>, <code>tracking_provider<\/code>, <code>shipping_method<\/code>, <code>date_created<\/code>, <code>date_modified<\/code>, <code>total<\/code>, <code>currency<\/code>, <code>line_items<\/code>.<\/p>\n\n<p>Query parameters (all catalog endpoints):<\/p>\n\n<ul>\n<li><code>page<\/code> \u2014 page number (default: 1, minimum: 1)<\/li>\n<li><code>per_page<\/code> \u2014 items per page (default: 100, maximum: 200)<\/li>\n<li><code>attribute_id<\/code> \u2014 (attribute-terms only) filter terms to a single attribute<\/li>\n<li><code>product_ids<\/code> \u2014 (variants only) comma-separated parent product IDs; returns variants grouped by product<\/li>\n<li><code>ids<\/code> \u2014 (variants only) comma-separated variation IDs; returns a flat list in request order<\/li>\n<li><code>id<\/code> \u2014 (variant \/ order) single variation or WooCommerce order ID filter<\/li>\n<li><code>external_order_id<\/code> \u2014 (order only) filter by 2khat external order id meta<\/li>\n<li><code>status<\/code> \u2014 (order only) optional WooCommerce status filter<\/li>\n<li><code>debug<\/code> \u2014 include SQL query stats only when <code>WP_DEBUG<\/code> and <code>TWOKCS_DEBUG<\/code> are enabled, or when the <code>twokcs_allow_debug<\/code> filter returns true. Full query details require <code>SAVEQUERIES<\/code> enabled in <code>wp-config.php<\/code>.<\/li>\n<\/ul>\n\n<!--section=installation-->\n<ol>\n<li>Upload the <code>2khat<\/code> folder to <code>\/wp-content\/plugins\/<\/code>.<\/li>\n<li>Activate the plugin through the WordPress Plugins screen.<\/li>\n<li>Ensure WooCommerce is installed and active.<\/li>\n<li>Confirm <code>public_key.pem<\/code> is present in the plugin directory.<\/li>\n<\/ol>\n\n<!--section=changelog-->\n<h4>1.0.8<\/h4>\n\n<ul>\n<li><code>GET \/order<\/code> returns a paginated list; <code>id<\/code>, <code>external_order_id<\/code>, and <code>status<\/code> are optional filters<\/li>\n<\/ul>\n\n<h4>1.0.7<\/h4>\n\n<ul>\n<li>Add create order (<code>POST \/orders<\/code>) and track order (<code>GET \/order<\/code>) endpoints<\/li>\n<\/ul>\n\n<h4>1.0.6<\/h4>\n\n<ul>\n<li>Align text domain with WordPress.org slug <code>2khat-catalog-sync<\/code><\/li>\n<\/ul>\n\n<h4>1.0.5<\/h4>\n\n<ul>\n<li>Rename all plugin globals from <code>dokhat<\/code> to <code>twokcs<\/code> prefix for WordPress.org compliance<\/li>\n<li>Update REST namespace to <code>twokcs\/v1<\/code> and auth scheme to <code>Twokcs<\/code><\/li>\n<\/ul>\n\n<h4>1.0.4<\/h4>\n\n<ul>\n<li>Align plugin folder and main file name with WordPress.org slug <code>2khat<\/code><\/li>\n<li>Fix auth header documentation to match the <code>Dokhat<\/code> scheme accepted by the plugin<\/li>\n<\/ul>\n\n<h4>1.0.3<\/h4>\n\n<ul>\n<li>Rename display name to 2khat Catalog Sync (WordPress.org trademark requirement)<\/li>\n<\/ul>\n\n<h4>1.0.2<\/h4>\n\n<ul>\n<li>Rename plugin for WordPress.org compliance (2khat WooCommerce Catalog Sync)<\/li>\n<li>Remove runtime SAVEQUERIES global side effects from debug mode<\/li>\n<li>Document public_key.pem as intentional RSA public key<\/li>\n<\/ul>\n\n<h4>1.0.1<\/h4>\n\n<ul>\n<li>Align plugin metadata for WordPress.org submission<\/li>\n<\/ul>\n\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>Initial 2khat release<\/li>\n<li>Modular plugin architecture<\/li>\n<li>RSA domain authentication with 2khat key pair<\/li>\n<li>Optimized bulk product export endpoint<\/li>\n<li>Compatibility with Discount Rules for WooCommerce and Woodmart theme<\/li>\n<\/ul>","raw_excerpt":"Official WooCommerce catalog sync plugin for the 2khat platform.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/pt-ao.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/327500","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pt-ao.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/pt-ao.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/pt-ao.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=327500"}],"author":[{"embeddable":true,"href":"https:\/\/pt-ao.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/mohammad61"}],"wp:attachment":[{"href":"https:\/\/pt-ao.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=327500"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/pt-ao.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=327500"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/pt-ao.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=327500"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/pt-ao.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=327500"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/pt-ao.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=327500"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/pt-ao.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=327500"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}