Use official WooCommerce Product Add-Ons compatibility
Use this reference when an existing catalog client, PHP integration, automation, or webhook expects the public contracts of WooCommerce Product Add-Ons 8.4.1. POM exposes these contracts only while the official extension is inactive.
Choose the correct contract
| Goal | Contract |
|---|---|
| Manage POM groups, reusable choices, advanced assignments, publications, or integrity | pom-tweaks/v1 management API |
| Keep an existing official Product Add-Ons v1 client | wc-product-add-ons/v1 |
| Keep an existing official global-group v2 client | wc-product-add-ons/v2 |
| Read or write add-ons with a native WooCommerce product client | addons and exclude_global_add_ons on the WooCommerce product REST response |
| Keep an existing WooCommerce automation | Official-compatible Abilities |
| Keep a PHP integration | Lazy official-compatible facade and supported hooks |
Do not activate both storefront engines. When WooCommerce Product Add-Ons is active, POM leaves the official routes, facade classes, Store API compatibility data, hooks, form handling, pricing, and order metadata to that extension.
REST routes and native product fields
The compatibility routes require an administrator or shop manager:
| Contract | Routes and methods |
|---|---|
| REST v1 collection | GET, POST /wp-json/wc-product-add-ons/v1/product-add-ons |
| REST v1 item | GET, PUT, PATCH, DELETE /wp-json/wc-product-add-ons/v1/product-add-ons/{id} |
| REST v2 collection | GET, POST /wp-json/wc-product-add-ons/v2/global-add-ons |
| REST v2 item | GET, PUT, PATCH, DELETE /wp-json/wc-product-add-ons/v2/global-add-ons/{id} |
| Native product REST | addons and exclude_global_add_ons on supported WooCommerce product endpoints |
The v1 routes preserve observable legacy scalar values, blank image values, option-key presence, and validation errors. The v2 routes preserve the official group schema and defaults. Official writes use the same POM validation and storage as the POM management API.
Individual group and native product management responses include a strong ETag. Send it in If-Match when updating or deleting. The official body remains unchanged; the header adds concurrency protection. A stale write returns HTTP 409 and a write without a precondition returns HTTP 428.
The official global-group schema can represent all-product and category assignments only. POM omits a group assigned solely to named products or advanced rules from the global-group collection rather than describing it incorrectly. Its effective fields still appear in that product's native addons field and POM public product model.
WooCommerce Abilities
When the installed WooCommerce version provides the Abilities API, POM registers:
woocommerce-product-addons/get-product-add-onswoocommerce-product-addons/get-global-add-on-groups
The abilities are read-only and use the same permissions, effective product resolution, official field shapes, and group visibility limits as their official counterparts.
Stable numeric identities
POM uses UUIDs internally and at its native Store API boundary. Compatibility responses additionally preserve integer identities:
- Product Add-On field IDs remain stable in native product REST, compatibility REST, Abilities, Store API compatibility data, cart
addonsrows,_pao_ids, order REST, and webhooks. - Global-group IDs remain integers in their own official namespace.
- Options keep official positional indexes; they do not receive a separate numeric ID.
- Mappings are site-scoped on multisite. Retired IDs are not reused.
Imported IDs are reserved before saving. A numeric ID already owned by another UUID is rejected instead of being linked by label or silently reassigned. Cloning creates new UUIDs and numeric mappings; preserving or linking an existing UUID keeps its established mapping.
Before changing an upgraded catalog that already contained POM definitions, run the legacy-ids inspection described in Migrate from WooCommerce Product Add-Ons.
Store API compatibility input and output
An official-compatible Store API client may submit addons_configuration with numeric field IDs and positional option indexes. A POM-native client submits pom_product_addons with UUIDs. Do not mix both properties in one request.
Accepted cart items expose the official-compatible extensions.addons.addons_data result as well as the POM result. Trusted PHP integrations that pass an official cart_item_data['addons'] array directly to WC_Cart::add_to_cart() retain supported labels, values, price types, cart pricing, and order metadata. That array is trusted server-created data, not a safe format for unsanitized browser input.
PHP facade
Check a class before calling it:
if (class_exists('WC_Product_Addons_Helper')) {
$addons = WC_Product_Addons_Helper::get_product_addons($product_id);
}
The facade loads a class only when PHP first requests it.
WC_Product_Addons_Helper supports official product and parent resolution, global groups, priority and exclusion behavior, prefixes, price-display and tax-mode helpers, required and description checks, restriction data, upload-size checks, date helpers, default values, numeric ID generation, cloned-price products, placeholder images, and editable cart permalinks.
WC_Product_Addons_Groups, WC_Product_Addons_Global_Group, and WC_Product_Addons_Product_Group support official group reads. Their supported create, update, and delete methods use POM validation, relationship protection, and persistence.
WC_Product_Addons_Display supports option detection, loop button text and URLs, AJAX-add-to-cart decisions, grouped-product decisions, POM asset loading, and cart edit permalinks. Constructing it does not register a duplicate WooCommerce hook set.
WC_Product_Addons_Html_Generator exists for feature detection, but the legacy addon-* input renderer is unsupported. POM forms use UUID field names and server validation; emitting official input names would create an unsafe form. Unsupported facade calls emit _doing_it_wrong() and return WP_Error when the official return type permits it; HTML methods return no markup.
Supported official PHP hooks
POM emits supported Product Add-Ons 8.4.1 hooks only on equivalent runtime paths. The official extension is the sole owner when active, so a callback is not run twice.
Resolution and helper hooks:
get_product_addons_product_terms,get_parent_product_addons_fields,get_product_addons_fields,get_product_addons,product_addons_field_prefix;addons_add_to_cart_text,addons_add_to_cart_url,wc_pao_restriction_data,woocommerce_addons_cloned_product_with_filtered_price;woocommerce_pao_date_input_timezone_reference,woocommerce_product_addons_cart_permalink,woocommerce_product_addons_no_image_select_placeholder_src,woocommerce_product_addons_show_num_chars.
Storefront and asset hooks:
woocommerce_product_addons_start,woocommerce_product_addons_end,wc_product_addon_start,wc_product_addon_options,wc_product_addon_end;woocommerce_addons_product_page_container_classes,woocommerce_product_addons_price_raw,woocommerce_product_addons_price,woocommerce_product_addons_option_price_raw,woocommerce_product_addons_option_price;woocommerce_addons_add_product_price_to_value,woocommerce_product_addons_image_swatch_size,woocommerce_product_addons_show_grand_total,woocommerce_pao_reset_date_link,woocommerce_pao_reset_file_link,woocommerce_pao_script_dependencies,woocommerce_price_trim_zeros.
Validation, cart, import, and order hooks:
woocommerce_product_addons_validate_value,woocommerce_validate_posted_addon_data,woocommerce_product_addon_cart_item_data,woocommerce_product_addon_reorder_cart_item_data,woocommerce_product_addon_reorder_disable_validation;woocommerce_product_addons_add_to_cart_product_types,woocommerce_product_addons_adjust_price,woocommerce_product_addons_update_product_price,woocommerce_addons_add_cart_price_to_value,woocommerce_product_addons_get_item_data,woocommerce_product_addons_upload_dir;woocommerce_product_addons_import_data,woocommerce_product_addons_display_editing_in_order_button,woocommerce_product_addons_editing_in_order_validate,woocommerce_product_addons_editing_in_order_form,woocommerce_product_addons_editing_in_order;woocommerce_product_addons_get_order_item_price,woocommerce_addons_add_order_price_to_value,woocommerce_product_addons_order_line_item_meta.
Callbacks receive official field or cart-row shapes. They are trusted application code and must return the documented type and preserve required keys. POM still validates browser values against the current UUID-backed definition.
Order REST and webhook compatibility
Orders retain one visible line-item metadata entry per accepted add-on plus compatible internal _pao_ids and _pao_total evidence. Native WooCommerce order REST responses and webhooks use the same customer-facing shape.
POM also preserves these established webhook additions:
- a line metadata key containing a euro amount in parentheses receives numeric
addon_price; - order metadata
checkout_delivery_typeis copied to top-leveltype; - order metadata
checkout_table_codeis copied to top-leveltable_id.
For example, metadata whose key is Sauce (2€) keeps key and value and receives "addon_price": 2. Historical order rows are not recalculated from current product definitions.
Verify compatibility
- Read a simple product and a variation through native WooCommerce REST, compatibility REST, the ability, and
WC_Product_Addons_Helper::get_product_addons(). - Confirm the same field IDs appear in product REST, Store API compatibility data, cart rows,
_pao_ids, order REST, and a webhook. - Update a group with its current
If-Match, then repeat the stale request and confirm it receives409without changing the record. - Confirm a named-product-only group is omitted from the global collection but appears in that product's resolved
addonsfield. - Register a temporary callback for one supported hook and confirm it runs once on its equivalent flow.
- Activate the official extension in a controlled environment and confirm POM's facade, official routes, abilities, and storefront behavior remain dormant.
Troubleshooting
- Missing class or route: confirm the POM tweak is enabled, WooCommerce is active, and the official extension is inactive.
- Unsupported facade method: move the integration to a supported helper or the POM management API instead of relying on legacy administration HTML or request injection.
- Missing global group: its product-only or advanced scope cannot be represented by the official global schema; resolve the product or use the POM API.
- Compatibility-ID collision: inspect and rebuild the site-scoped ID registry before retrying; do not edit IDs by hand.
Related: Management REST API, Store API and Blocks, and Integration reference.