Skip to main content
Version: 2026.1

Studio Integration

Studio API Endpoints

The Ecommerce Framework Bundle provides a RESTful API for the Pimcore Studio interface, enabling management of pricing rules, access to product index data, and back-office order management. All endpoints are prefixed with /pimcore-studio/api/bundle/ecommerce and require appropriate permissions.


Index

List Tenants

Endpoint: GET /tenants Operation ID: bundle_ecommerce_tenants_collection Permission: bundle_ecommerce_back-office_order

Returns a list of all configured ecommerce tenants.

Response: Paginated collection of Tenant objects


List Index Fields

Endpoint: GET /fields Operation ID: bundle_ecommerce_fields_collection Permission: bundle_ecommerce_back-office_order

Returns a list of product index fields, with optional filtering by filter group, tenant, and visibility.

Query Parameters:

  • filtergroup (string, optional): Filter by specific filter groups, comma-separated (e.g. category,price)
  • tenant (string, optional): Filter by tenant
  • showAllFields (boolean, optional): Include hidden fields (default: false)
  • addEmpty (boolean, optional): Prepend an empty option to the list (default: false)
  • specificPriceField (boolean, optional): Append the specific price field (default: false)

Response: Paginated collection of IndexField objects

Example:

GET /fields?filtergroup=category,price&tenant=default&showAllFields=true

List Filter Groups

Endpoint: GET /filter-groups Operation ID: bundle_ecommerce_filter_groups_collection Permission: bundle_ecommerce_back-office_order

Returns a list of all available filter groups for the product index.

Response: Paginated collection of FilterGroup objects


List Filter Field Values

Endpoint: GET /index/filter-field-values Operation ID: ecommerce_index_get_filter_field_values_collection Permission: bundle_ecommerce_back-office_order

Returns all distinct values for a given filter field, enabling filter configuration in the back office.

Query Parameters:

  • field (string, required): The filter field to retrieve values for (e.g. categoryIds)
  • tenant (string, optional): The tenant to use for filtering (e.g. default)

Response: Paginated collection of FilterFieldValue objects

Possible Errors:

  • 404 Not Found: The specified field does not exist in the index

Example:

GET /index/filter-field-values?field=categoryIds&tenant=default

Pricing Rules

List Pricing Rules

Endpoint: GET /pricing/rules Operation ID: bundle_ecommerce_pricing_rules_collection Permission: bundle_ecommerce_pricing_rules

Returns a list of all configured pricing rules with their basic properties.

Response: Paginated collection of PricingRuleListItem objects

Each item contains:

  • id (integer): Rule ID
  • name (string): Internal rule name
  • label (string): Localized display label (current locale)
  • behavior (string): Rule behavior — additiv or stopExecute
  • active (boolean): Whether the rule is currently active
  • prio (integer): Display/execution priority

Get Pricing Rule

Endpoint: GET /pricing/rules/{id} Operation ID: bundle_ecommerce_pricing_rules_item Permission: bundle_ecommerce_pricing_rules

Returns the full details of a single pricing rule, including its localized labels and descriptions, condition tree, and action configurations.

Path Parameter:

  • id (integer): The ID of the pricing rule

Response: PricingRuleDetail object

The detail object contains:

  • id, name, behavior, active, prio — same as list item
  • label (object): Localized labels keyed by language code (e.g. {"en": "Summer Sale", "de": "Sommerschluss"})
  • description (object): Localized descriptions keyed by language code
  • condition (object|null): Decoded condition tree, or null if no condition is set
  • actions (array): List of action configuration objects

Possible Errors:

  • 404 Not Found: No pricing rule with the given ID exists

Example:

GET /pricing/rules/6

Get Pricing Config

Endpoint: GET /pricing/config Operation ID: bundle_ecommerce_pricing_config Permission: bundle_ecommerce_pricing_rules

Returns the list of all registered condition type keys and action type keys available for building pricing rule conditions and actions.

Response: PricingConfig object

  • conditions (string[]): Available condition type identifiers (e.g. CartAmount, Voucher, DateRange, ...)
  • actions (string[]): Available action type identifiers (e.g. CartDiscount, Gift, FreeShipping, ...)

Create Pricing Rule

Endpoint: POST /pricing/rules Operation ID: bundle_ecommerce_pricing_rules_create Permission: bundle_ecommerce_pricing_rules

Creates a new pricing rule with the given name. The rule is created with default settings and must be fully configured via the save endpoint afterwards.

Request Body: JSON object

FieldTypeRequiredDescription
namestringyesInternal name for the rule. Must be non-empty, max 190 characters, and
contain only letters, digits, -, and _.

Response: JSON object with the ID of the newly created rule:

{ "id": 42 }

Possible Errors:

  • 422 Unprocessable Entity: Name is empty, too long, contains invalid characters, or a rule with that name already exists

Example:

POST /pricing/rules
Content-Type: application/json

{ "name": "summer_sale" }

Save Pricing Rule

Endpoint: PUT /pricing/rules/{id} Operation ID: bundle_ecommerce_pricing_rules_save Permission: bundle_ecommerce_pricing_rules

Updates a pricing rule's full configuration, including behavior, active state, priority, localized labels and descriptions, condition tree, and actions. Returns the updated rule detail.

Path Parameter:

  • id (integer): The ID of the pricing rule to update

Request Body: JSON object (PricingRuleSaveParameters)

FieldTypeRequiredDescription
behaviorstringyesadditiv or stopExecute
activebooleanyesWhether the rule is active
priointegeryesExecution/display priority
labelobjectyesLocalized labels keyed by language code (e.g. {"en": "Summer Sale"})
descriptionobjectyesLocalized descriptions keyed by language code
conditionobject|nullnoCondition tree as a decoded JSON object, or null to remove
actionsarrayyesList of action configuration objects

Response: Updated PricingRuleDetail object

Possible Errors:

  • 404 Not Found: No pricing rule with the given ID exists

Example:

PUT /pricing/rules/6
Content-Type: application/json

{
"behavior": "stopExecute",
"active": true,
"prio": 1,
"label": { "en": "Summer Sale", "de": "Sommerschluss" },
"description": { "en": "10% off all products" },
"condition": {
"type": "Pimcore\\Bundle\\EcommerceFrameworkBundle\\PricingManager\\Condition\\CartAmount",
"config": { "limit": 100 }
},
"actions": [{
"type": "Pimcore\\Bundle\\EcommerceFrameworkBundle\\PricingManager\\Action\\CartDiscount",
"config": { "percent": 10 }
}]
}

Delete Pricing Rule

Endpoint: DELETE /pricing/rules/{id} Operation ID: bundle_ecommerce_pricing_rules_delete Permission: bundle_ecommerce_pricing_rules

Permanently deletes a pricing rule.

Path Parameter:

  • id (integer): The ID of the pricing rule to delete

Response: HTTP 200 OK (empty body)

Possible Errors:

  • 404 Not Found: No pricing rule with the given ID exists

Example:

DELETE /pricing/rules/6

Copy Pricing Rule

Endpoint: POST /pricing/rules/{id}/copy Operation ID: bundle_ecommerce_pricing_rules_copy Permission: bundle_ecommerce_pricing_rules

Creates a duplicate of an existing pricing rule. The copy is given an auto-generated name based on the original.

Path Parameter:

  • id (integer): The ID of the pricing rule to copy

Response: HTTP 200 OK (empty body)

Possible Errors:

  • 404 Not Found: No pricing rule with the given ID exists

Example:

POST /pricing/rules/6/copy

Rename Pricing Rule

Endpoint: PUT /pricing/rules/{id}/rename Operation ID: bundle_ecommerce_pricing_rules_rename Permission: bundle_ecommerce_pricing_rules

Renames an existing pricing rule's internal name.

Path Parameter:

  • id (integer): The ID of the pricing rule to rename

Request Body: JSON object

FieldTypeRequiredDescription
namestringyesNew internal name. Same validation rules as for create: non-empty,
max 190 characters, letters/digits/-/_ only.

Response: HTTP 200 OK (empty body)

Possible Errors:

  • 404 Not Found: No pricing rule with the given ID exists
  • 422 Unprocessable Entity: Name is empty, too long, contains invalid characters, or a rule with that name already exists

Example:

PUT /pricing/rules/6/rename
Content-Type: application/json

{ "name": "winter_sale" }

Save Pricing Rule Order

Endpoint: PUT /pricing/rules/order Operation ID: bundle_ecommerce_pricing_rules_save_order Permission: bundle_ecommerce_pricing_rules

Updates the priority (display and execution order) of multiple pricing rules at once. Rules not included in the map are left unchanged. Unknown IDs are silently ignored.

Request Body: JSON object

FieldTypeRequiredDescription
rulesobjectyesMap of rule ID (string key) to new priority value (integer).

Response: HTTP 200 OK (empty body)

Example:

PUT /pricing/rules/order
Content-Type: application/json

{
"rules": { "6": 0, "7": 1, "8": 2, "9": 3, "10": 4 }
}

Permissions

ConstantValueUsed For
BUNDLE_ECOMMERCE_BACK_OFFICE_ORDERbundle_ecommerce_back-office_orderIndex endpoints
BUNDLE_ECOMMERCE_PRICING_RULESbundle_ecommerce_pricing_rulesPricing rule endpoints

Common Response Codes

  • 200 OK: Successful request
  • 401 Unauthorized: Missing or invalid authentication
  • 404 Not Found: Resource not found
  • 422 Unprocessable Entity: Validation failure (e.g. invalid or duplicate rule name)

API Tags

All endpoints are tagged with Ecommerce for OpenAPI documentation grouping.

Usage Examples

Managing Pricing Rules

  1. List all rules:

    GET /pricing/rules
  2. Get full details of a rule:

    GET /pricing/rules/6
  3. Create a new rule:

    POST /pricing/rules
    { "name": "black_friday" }
  4. Configure the new rule:

    PUT /pricing/rules/42
    {
    "behavior": "stopExecute", "active": true, "prio": 0,
    "label": { "en": "Black Friday" }, "description": {}, "actions": [...]
    }
  5. Reorder all rules:

    PUT /pricing/rules/order
    { "rules": { "42": 0, "6": 1, "7": 2 } }
  6. Copy an existing rule as a starting point:

    POST /pricing/rules/6/copy
  7. Delete a rule:

    DELETE /pricing/rules/6

Browsing Index Data

  1. List all tenants:

    GET /tenants
  2. List fields for a specific tenant:

    GET /fields?tenant=default
  3. List all filter groups:

    GET /filter-groups
  4. Get all values for a filter field:

    GET /index/filter-field-values?field=categoryIds&tenant=default

Orders

The order endpoints are split into two groups:

  • View endpoints return rendered HTML (Twig templates) intended for iframe embedding in the Pimcore Studio UI. They respond with Content-Type: text/html.
  • Mutation endpoints perform actions (cancel, edit, complaint) and return an empty 200 OK.

Order Views

List Orders

Endpoint: GET /orders/view/list Operation ID: bundle_ecommerce_orders_view_list Permission: bundle_ecommerce_back-office_order

Returns a rendered HTML page listing orders with pagination, filtering by date range, search query, and pricing rule. The response is the rendered list.html.twig template.

Query Parameters:

  • type (string, optional): List type — order (default) or order_item
  • q (string, optional): Free-text search query
  • search (string, optional): Search scope — order (default) or productType
  • from (string, optional): Filter from date in Y-m-d format (e.g. 2024-01-01). Defaults to first day of current month if neither from nor till is provided.
  • till (string, optional): Filter till date in Y-m-d format (e.g. 2024-12-31)
  • pricingRule (integer, optional): Filter by pricing rule ID
  • page (integer, optional): Page number, 1-based (default: 1)
  • limit (integer, optional): Number of results per page (default: 10)

Response: text/html — rendered order list page

Example:

GET /orders/view/list?type=order&q=Jane&from=2024-01-01&till=2024-12-31&page=1&limit=10

View Order Detail

Endpoint: GET /orders/{id}/view/detail Operation ID: bundle_ecommerce_orders_view_detail Permission: bundle_ecommerce_back-office_order

Returns a rendered HTML page showing the full details of a single order, including order items, payment information, invoice/delivery address geocoding, a chronological change log timeline, and customer account summary. The response is the rendered detail.html.twig template.

Path Parameter:

  • id (integer): The ID of the order

Response: text/html — rendered order detail page

Possible Errors:

  • 404 Not Found: No order with the given ID exists

Example:

GET /orders/42/view/detail

View Order Item Cancel Form

Endpoint: GET /orders/items/{id}/view/cancel Operation ID: bundle_ecommerce_orders_view_item_cancel Permission: bundle_ecommerce_back-office_order

Returns a rendered HTML form for cancelling an order item. The response is the rendered item_cancel.html.twig template, which displays the item details and a cancellation form.

Path Parameter:

  • id (integer): The ID of the order item

Response: text/html — rendered cancel form

Possible Errors:

  • 404 Not Found: No order item with the given ID exists

Example:

GET /orders/items/5/view/cancel

View Order Item Edit Form

Endpoint: GET /orders/items/{id}/view/edit Operation ID: bundle_ecommerce_orders_view_item_edit Permission: bundle_ecommerce_back-office_order

Returns a rendered HTML form for editing the quantity of an order item. The response is the rendered item_edit.html.twig template.

Path Parameter:

  • id (integer): The ID of the order item

Response: text/html — rendered edit form

Possible Errors:

  • 404 Not Found: No order item with the given ID exists

Example:

GET /orders/items/5/view/edit

View Order Item Complaint Form

Endpoint: GET /orders/items/{id}/view/complaint Operation ID: bundle_ecommerce_orders_view_item_complaint Permission: bundle_ecommerce_back-office_order

Returns a rendered HTML form for filing a complaint about an order item. The response is the rendered item_complaint.html.twig template.

Path Parameter:

  • id (integer): The ID of the order item

Response: text/html — rendered complaint form

Possible Errors:

  • 404 Not Found: No order item with the given ID exists

Example:

GET /orders/items/5/view/complaint

Order Item Mutations

Cancel Order Item

Endpoint: POST /orders/items/{id}/cancel Operation ID: bundle_ecommerce_orders_item_cancel_post Permission: bundle_ecommerce_back-office_order

Cancels the specified order item. An optional message can be attached to the cancellation note for audit trail purposes. Returns an empty 200 OK response on success.

Path Parameter:

  • id (integer): The ID of the order item to cancel

Request Body: JSON object (OrderItemCancelParameters)

FieldTypeRequiredDescription
messagestringnoOptional message to attach to the cancel note (default: empty string)

Response: Empty 200 OK

Possible Errors:

  • 404 Not Found: No order item with the given ID exists

Example:

POST /orders/items/5/cancel
Content-Type: application/json

{ "message": "Customer requested cancellation." }

Edit Order Item

Endpoint: PUT /orders/items/{id}/edit Operation ID: bundle_ecommerce_orders_item_edit_put Permission: bundle_ecommerce_back-office_order

Updates the quantity of the specified order item. An optional message can be attached to the edit note for audit trail purposes. Returns an empty 200 OK response on success.

Path Parameter:

  • id (integer): The ID of the order item to edit

Request Body: JSON object (OrderItemEditParameters)

FieldTypeRequiredDescription
quantitynumber (float)yesNew quantity for the order item
messagestringnoOptional message to attach to the edit note (default: empty string)

Response: Empty 200 OK

Possible Errors:

  • 404 Not Found: No order item with the given ID exists

Example:

PUT /orders/items/5/edit
Content-Type: application/json

{ "quantity": 3.0, "message": "Customer changed mind." }

File Order Item Complaint

Endpoint: POST /orders/items/{id}/complaint Operation ID: bundle_ecommerce_orders_item_complaint_post Permission: bundle_ecommerce_back-office_order

Files a complaint for the specified order item for a given quantity. An optional message can be attached to the complaint note for audit trail purposes. Returns an empty 200 OK response on success.

Path Parameter:

  • id (integer): The ID of the order item to complain about

Request Body: JSON object (OrderItemComplaintParameters)

FieldTypeRequiredDescription
quantitynumber (float)yesQuantity subject to the complaint
messagestringnoOptional message to attach to the complaint note (default: empty string)

Response: Empty 200 OK

Possible Errors:

  • 404 Not Found: No order item with the given ID exists

Example:

POST /orders/items/5/complaint
Content-Type: application/json

{ "quantity": 1.0, "message": "Item arrived damaged." }

Context-Aware Routing and Form Interception

The order Twig templates are shared between the legacy admin interface and the Pimcore Studio iframe context. Since the Studio iframe operates under the pimcore-studio firewall, all URLs within the templates must resolve to Studio routes when rendered in that context.

How It Works

The OrderViewService passes studioContext: true to every twig->render() call. Each template checks {% set studioContext = studioContext|default(false) %} and conditionally switches route names:

  • View links (list, detail, edit form, cancel form, complaint form) use pimcore_studio_api_ecommerce_orders_view_* routes in Studio context and pimcore_ecommerce_backend_admin-order_* routes in the legacy context.
  • Pagination (paging.html.twig) uses pimcore_url() which resolves relative to the current route — no changes needed.
  • List search form has no explicit action attribute and submits to the current URL — works in both contexts without changes.

JavaScript Form Interception for Mutations

The Studio mutation endpoints (cancel, edit, complaint) expect JSON request bodies and use #[MapRequestPayload] for deserialization. Traditional HTML form POST submissions send application/x-www-form-urlencoded data, which is incompatible.

In Studio context, the item form templates (cancel, edit, complaint) add data-studio-context, data-studio-method, and data-studio-redirect attributes to the <form> element. A <script> block intercepts the form submit event and:

  1. Prevents the default form submission.
  2. Collects form field values into a JSON object matching the mutation endpoint's schema.
  3. Sends the JSON payload via fetch() to the mutation endpoint URL using the correct HTTP method (POST for cancel/complaint, PUT for edit).
  4. On a successful response, redirects the browser to the order detail view page.

This approach keeps the mutation controllers as clean JSON APIs with no HTML rendering concerns. When the templates are eventually replaced with a dedicated Studio UI, the mutation endpoints remain unchanged.

CSRF Token Handling

In legacy context, forms include a hidden csrfToken field validated by the legacy admin controller. In Studio context, authentication is handled by the Studio firewall session, so the CSRF token input is conditionally omitted:

{% if not studioContext %}
<input type="hidden" name="csrfToken" value="{{ pimcore_csrf.getCsrfToken(app.request.session) }}">
{% endif %}

Vouchers

The voucher endpoints manage voucher series tokens — generating, exporting, and cleaning up tokens and reservations. Like the order endpoints, they are split into:

  • View endpoint returning rendered HTML (Twig template) for iframe embedding.
  • Mutation endpoints performing actions and returning an empty 200 OK.

Voucher Views

View Voucher Code Tab

Endpoint: GET /vouchers/{id}/view/tab Operation ID: bundle_ecommerce_vouchers_view_tab Permission: bundle_ecommerce_pricing_rules

Returns a rendered HTML page showing the voucher code tab for a voucher series, including the token listing with pagination, filter controls, statistics, and action modals (generate, cleanup, cleanup reservations). Renders either the pattern or single token template depending on the token manager type.

Path Parameter:

  • id (integer): The ID of the voucher series

Query Parameters:

  • page (integer, optional): Page number, 1-based (default: 1)
  • tokensPerPage (integer, optional): Number of tokens per page (default: 25)
  • token (string, optional): Filter by token code
  • creation_from (string, optional): Filter from date in Y-m-d format
  • creation_to (string, optional): Filter to date in Y-m-d format
  • usages (integer, optional): Filter by usage count
  • length (integer, optional): Filter by token length
  • sort_criteria (string, optional): Sort field (e.g. token, usages, length, timestamp)
  • sort_order (string, optional): Sort direction: ASC or DESC

Response: text/html — rendered voucher code tab page

Possible Errors:

  • 404 Not Found: No voucher series with the given ID exists

Example:

GET /vouchers/42/view/tab?page=1&tokensPerPage=25&sort_criteria=timestamp&sort_order=DESC

Voucher Token Operations

Export Tokens

Endpoint: GET /vouchers/{id}/tokens/export Operation ID: bundle_ecommerce_vouchers_tokens_export Permission: bundle_ecommerce_pricing_rules

Exports all voucher tokens for a series as a file download. The token manager must implement ExportableTokenManagerInterface.

Path Parameter:

  • id (integer): The ID of the voucher series

Query Parameters:

  • format (string, optional): Export format — csv (default) or plain

Response: File download (text/csv or text/plain)

Possible Errors:

  • 404 Not Found: No voucher series with the given ID exists
  • 500 Environment Error: Token manager does not support exporting

Example:

GET /vouchers/42/tokens/export?format=csv

Generate Tokens

Endpoint: POST /vouchers/{id}/tokens/generate Operation ID: bundle_ecommerce_vouchers_tokens_generate Permission: bundle_ecommerce_pricing_rules

Generates or updates voucher tokens for a series based on the configured token manager settings.

Path Parameter:

  • id (integer): The ID of the voucher series

Response: Empty 200 OK

Possible Errors:

  • 404 Not Found: No voucher series with the given ID exists
  • 500 Environment Error: Token generation failed

Example:

POST /vouchers/42/tokens/generate

Cleanup Tokens

Endpoint: POST /vouchers/{id}/tokens/cleanup Operation ID: bundle_ecommerce_vouchers_tokens_cleanup Permission: bundle_ecommerce_pricing_rules

Cleans up voucher tokens by usage status, with an optional date filter to only remove tokens older than a given date.

Path Parameter:

  • id (integer): The ID of the voucher series

Request Body: JSON object (CleanupTokensParameters)

FieldTypeRequiredDescription
usagestringyesWhich tokens to clean up: used, unused, or both
olderThanstringnoOnly remove tokens older than this date (format: Y-m-d)

Response: Empty 200 OK

Possible Errors:

  • 404 Not Found: No voucher series with the given ID exists
  • 500 Environment Error: Token cleanup failed

Example:

POST /vouchers/42/tokens/cleanup
Content-Type: application/json

{ "usage": "used", "olderThan": "2024-01-01" }

Cleanup Reservations

Endpoint: POST /vouchers/{id}/reservations/cleanup Operation ID: bundle_ecommerce_vouchers_reservations_cleanup Permission: bundle_ecommerce_pricing_rules

Cleans up voucher token reservations that are older than a specified duration in minutes.

Path Parameter:

  • id (integer): The ID of the voucher series

Request Body: JSON object (CleanupReservationsParameters)

FieldTypeRequiredDescription
durationintegeryesRemove reservations older than this many minutes

Response: Empty 200 OK

Possible Errors:

  • 404 Not Found: No voucher series with the given ID exists
  • 500 Environment Error: Reservation cleanup failed

Example:

POST /vouchers/42/reservations/cleanup
Content-Type: application/json

{ "duration": 5 }

Context-Aware Routing for Voucher Templates

The voucher Twig templates use the same context-aware routing pattern as the order templates. The VoucherViewService passes studioContext: true to every render call.

Route Mapping

Legacy RouteStudio Route
pimcore_ecommerce_backend_voucher_export-tokenspimcore_studio_api_ecommerce_vouchers_tokens_export
pimcore_ecommerce_backend_voucher_generatepimcore_studio_api_ecommerce_vouchers_tokens_generate
pimcore_ecommerce_backend_voucher_cleanuppimcore_studio_api_ecommerce_vouchers_tokens_cleanup
pimcore_ecommerce_backend_voucher_cleanup-reservationspimcore_studio_api_ecommerce_vouchers_reservations_cleanup

Generate and Assign Modals

The generate modal (pattern/generate_modal.html.twig) and assign settings modal (single/assign_settings_modal.html.twig) use <a> links that in legacy context perform a GET redirect. In Studio context, the link targets the Studio POST endpoint and a JavaScript click interceptor sends the request via fetch() then redirects to the tab view.

Cleanup Form Modals

The cleanup tokens modal and cleanup reservations modal use the same form interception pattern as the order item mutations: in Studio context, data-studio-context, data-studio-method, and data-studio-redirect attributes are added to the form, and a script intercepts the submit event to send a JSON fetch() request instead of the traditional form POST. CSRF tokens are conditionally omitted in Studio context.