Composite Products developer reference

This reference covers the stable public surfaces for custom storefronts and supported integrations. The server remains authoritative for product membership, availability, rules, stock, Add-Ons, and price.

Browse chapter options

GET /wp-json/pom-tweaks/v1/composite-products/<product_id>/chapters/<chapter_id>/options

Supported query parameters are optional page_size from 1 to 50, the opaque cursor returned by the preceding response, search up to 100 characters, category_id, and up to 200 selected[] keys in product_id:variation_id format. When page_size is omitted, the chapter's Options per load applies; a value of 0 inherits the product's Default options per load, which defaults to 12. An explicit valid page_size overrides the saved default for that request. The server always enforces the maximum of 50; selected options are revalidated and returned separately from the discovery page.

The response separates current options from revalidated selected_options, lists unavailable selected keys, and returns has_more plus next_cursor. Never construct or persist a cursor. Restart from the first page when a cursor is invalidated by a product, term, or configuration change.

Discover component Add-Ons

GET /wp-json/pom-tweaks/v1/composite-products/<product_id>/chapters/<chapter_id>/components/<component_id>/addons

Add variation_id for an exact variation. Use the returned UUID-backed public model to build addons intent for a quote. Choice, checkbox, text, textarea, custom-price, input-multiplier, heading, and date fields are supported. File uploads and booking person or block multipliers are not representable in the Composite JSON contract.

Request a quote

POST /wp-json/pom-tweaks/v1/composite-products/<product_id>/quote

Example body:

{
  "quantity": 2,
  "selections": [
    {
      "chapter_id": "chapter-drinks",
      "items": [
        {
          "product_id": 125,
          "variation_id": 130,
          "quantity": 4,
          "addons": {
            "context-uuid": {
              "field-uuid": "option-uuid"
            }
          }
        }
      ]
    }
  ]
}

Omit variation_id or use zero for a simple product. quantity multiplies the complete configuration; each component quantity is the amount inside one configuration.

A successful response includes valid, quote_hash, configuration revision, chapter and item breakdowns, rule details, stock, tax-exclusive calculation totals, money_context, cart_allocation, and scenario_state. Business validation returns valid: false with machine-readable errors and no trusted totals. A malformed request or impossible stored configuration returns a REST error.

totals.management_fee is the effective tax-exclusive fee for one configuration. totals.management_fee_rule_id identifies the first enabled exact-combination rule that replaced the default; it is an empty string when the default applies or the product uses fixed-total pricing. Matching uses the complete validated selection across visible chapters, exact variation IDs, and the rule's quantity setting. The quote request still contains only selection intent: clients cannot submit a trusted fee or winning rule. Cart and Store API additions re-quote the same intent on the server.

On a valid storefront quote, POM Tweaks writes totals.unit_total_html into the main WooCommerce price amount and any POM Theme fixed product-bar price. The Composite summary continues to use totals.total_html, which includes the requested parent quantity. This keeps the standard product price as a per-configuration amount while the summary remains the full purchase total.

The Composite root then dispatches a bubbling pom:composite:unit-price-updated browser event. Its detail contains productId, valid, numeric unitTotal, numeric displayUnitTotal in the storefront tax context, and sanitized unitTotalHtml. When the quote is invalid, valid is false, unitTotal is null, unitTotalHtml is empty, and the original product price is restored. Custom themes can listen for this event when their visible product-price markup does not use WooCommerce's standard .summary .price or .entry-summary .price structure.

The request is limited to 65,536 bytes, eight nesting levels, 30 chapter entries, 200 selections per chapter, 200 selections in total, and whole-number quantities from 1 to 999. By default, public quote traffic permits 40 requests per 10 seconds for its primary customer or browser identity plus a broader 400-request anonymous network ceiling. A limited response uses status 429 and standard retry headers.

Configuration limits

Contract Maximum
Chapters per Composite product 30
IDs in one product, category, or exclusion selector 200
Source and exclusion IDs across one product 2,000
Products in one saved category snapshot 1,000
Pricing rules in one product or category list 100
Management fee rules per Composite product 100
Distinct products or variations in one fee combination 200
Pricing rules across global and chapter scopes 500
Scenarios per product 100
Conditions or actions in one scenario 20
Compatibility rules per product 100
Reusable chapter entries per site 200
Import JSON file 1 MB

The editor prevents new rows at visible limits. Server validation rejects a modified request above a limit without truncating the configuration or replacing the last valid saved value.

Error contracts

Structural failures use stable pom_composite_* codes and include a JSON Pointer-compatible data.path when a request location is available. Important examples include:

  • pom_composite_quote_body_too_large with status 413;
  • pom_composite_quote_body_too_deep;
  • pom_composite_duplicate_chapter_selection;
  • pom_composite_duplicate_selected_item;
  • pom_composite_too_many_selected_items; and
  • pom_composite_unknown_chapter with status 400.

An invalid stored configuration returns a matching pom_composite_configuration_* error with status 409 instead of evaluating a partial definition. Rate limiting returns pom_composite_quote_rate_limited with status 429 and retry headers. WordPress argument-schema failures may use rest_invalid_param.

Store API add to cart

Send the same selection contract under extensions.pom-composite.selections. POM Tweaks re-quotes and performs the same atomic parent-and-components insertion used by the product form. Store API cart rows expose the group relationship and keep component quantity and removal controls non-editable.

Supported PHP extension points

  • pom_tweaks_composite_component_product_types adds a product-type slug to administration search and server eligibility. The custom type must still be compatible with the storefront and cart lifecycle.
  • pom_tweaks_composite_builder_hooks extends the allowlisted builder positions. Values must name real action hooks; the built-in symbolic pom_composite_description_start and pom_composite_description_end positions are handled through the product long description.
  • pom_tweaks_composite_summary_hooks extends the allowlisted WordPress action positions used by every layout, including Slot builder. Each product registers its configured summary action once; the storefront removes the hidden inline fallback when that action renders successfully.
  • pom_tweaks_product_addons_component_summary supplies the bounded Product Add-Ons discovery summary used to avoid loading a full component contract when no configurable fields exist.
  • pom_tweaks_composite_before_builder and pom_tweaks_composite_after_builder run around the builder.
  • pom_tweaks_composite_before_chapter and pom_tweaks_composite_after_chapter run around a chapter.
  • pom_tweaks_composite_storefront_option filters prepared display data, never authoritative price.
  • pom_tweaks_composite_before_component_validation, pom_tweaks_composite_validate_component, and pom_tweaks_composite_after_component_validation support container integrations during quote and cart validation.
  • pom_tweaks_composite_component_cart_item_data adds non-authoritative component-line data and cannot replace reserved identity, Add-On snapshots, or price.

Example custom product-type eligibility:

add_filter(
    'pom_tweaks_composite_component_product_types',
    static function (array $types): array {
        $types[] = 'my_product_type';

        return $types;
    }
);

Operational integrations can adjust the bounded quote limiter through pom_tweaks_composite_quote_rate_limit and trusted identity filters. pom_tweaks_composite_quote_observed exposes aggregate duration and workload fields without selections, product names, customer data, cookies, nonces, or network identifiers. Opt-in WooCommerce logging is controlled by pom_tweaks_composite_quote_logging_enabled and is disabled by default.