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_largewith status 413;pom_composite_quote_body_too_deep;pom_composite_duplicate_chapter_selection;pom_composite_duplicate_selected_item;pom_composite_too_many_selected_items; andpom_composite_unknown_chapterwith 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_typesadds 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_hooksextends the allowlisted builder positions. Values must name real action hooks; the built-in symbolicpom_composite_description_startandpom_composite_description_endpositions are handled through the product long description.pom_tweaks_composite_summary_hooksextends 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_summarysupplies the bounded Product Add-Ons discovery summary used to avoid loading a full component contract when no configurable fields exist.pom_tweaks_composite_before_builderandpom_tweaks_composite_after_builderrun around the builder.pom_tweaks_composite_before_chapterandpom_tweaks_composite_after_chapterrun around a chapter.pom_tweaks_composite_storefront_optionfilters prepared display data, never authoritative price.pom_tweaks_composite_before_component_validation,pom_tweaks_composite_validate_component, andpom_tweaks_composite_after_component_validationsupport container integrations during quote and cart validation.pom_tweaks_composite_component_cart_item_dataadds 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.