├── .gitignore ├── assets └── images │ └── reference-screenshot.png ├── .spectral.mjs ├── enhance.yml ├── .github ├── chainguard │ └── release.sts.yaml ├── workflows │ ├── validate_descriptions.yml │ ├── schedule_versions.yml │ ├── manual_versioning.yml │ ├── plugin_commercial_schema.yml │ ├── plugin_customproducts_schema.yml │ ├── plugin_digitalsalesroom_schema.yml │ └── base_schema.yml └── scripts │ ├── extract.sh │ └── find_delta_paths.sh ├── flake.nix ├── README.md ├── flake.lock ├── docs ├── resources │ ├── libraries-sdks │ │ ├── php.md │ │ └── python.md │ └── entity-reference.md ├── concepts │ ├── endpoint-structure │ │ ├── reading-entities.md │ │ ├── request-response-structure.md │ │ └── writing-entities │ │ │ ├── README.md │ │ │ ├── bulk-payloads.md │ │ │ ├── associations.md │ │ │ └── product-data.md │ └── authentication-authorisation.md └── guides │ └── quick-start │ ├── 04-document-management.md │ ├── 01-introduction.md │ ├── 03-media-handling.md │ ├── 06-cms-handling.md │ ├── 05-order-management.md │ └── 02-product-management.md ├── toc.json ├── SwagCustomizedProducts-adminapi.summary.json ├── SwagDigitalSalesRooms-adminapi.summary.json └── SwagCommercial-adminapi.summary.json /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .idea -------------------------------------------------------------------------------- /assets/images/reference-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopware/admin-api-reference/HEAD/assets/images/reference-screenshot.png -------------------------------------------------------------------------------- /.spectral.mjs: -------------------------------------------------------------------------------- 1 | import ruleset from "https://stoplight.io/api/v1/projects/cHJqOjEwNjA0Mw/spectral.js?branch=quick-starter&token=260369f1-b86f-419b-afd4-8c43dd71e5d4"; 2 | export default { extends: ruleset }; -------------------------------------------------------------------------------- /enhance.yml: -------------------------------------------------------------------------------- 1 | .paths./salutation.post.summary: > 2 | Fetches salutations with a criteria obj. 3 | 4 | .paths./_action/number-range/reserve/{type}/{saleschannel}.get.summary: > 5 | Reserve or preview a number-range / document number. 6 | -------------------------------------------------------------------------------- /.github/chainguard/release.sts.yaml: -------------------------------------------------------------------------------- 1 | issuer: https://token.actions.githubusercontent.com 2 | subject_pattern: repo:shopware/shopware:ref:refs/tags/v[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+ 3 | claim_pattern: 4 | job_workflow_ref: shopware/shopware/.github/workflows/05-publish-release.yml@refs/tags/v[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+ 5 | 6 | permissions: 7 | actions: write 8 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "A very basic flake"; 3 | 4 | inputs = { 5 | nixpkgs.url = "github:nixos/nixpkgs"; 6 | }; 7 | 8 | outputs = { 9 | self, 10 | nixpkgs, 11 | }: let 12 | pkgs = nixpkgs.legacyPackages.x86_64-linux; 13 | in { 14 | devShell.x86_64-linux = pkgs.mkShell { 15 | buildInputs = with pkgs; [yq-go alejandra shellcheck]; 16 | }; 17 | }; 18 | } 19 | -------------------------------------------------------------------------------- /.github/workflows/validate_descriptions.yml: -------------------------------------------------------------------------------- 1 | name: Validate descriptions.yml 2 | 3 | on: 4 | workflow_dispatch: 5 | pull_request: 6 | paths: 7 | - 'descriptions.yml' 8 | 9 | jobs: 10 | validate: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout 14 | uses: actions/checkout@v4 15 | 16 | - name: Validate with yq 17 | uses: mikefarah/yq@master 18 | with: 19 | cmd: yq 'true' descriptions.yml 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Shopware 6 Admin API Reference 2 | 3 | This repository reflects our official Admin API reference and documentation available on [shopware.stoplight.io/docs/admin-api](https://shopware.stoplight.io/docs/admin-api). 4 | 5 | ![Admin API Reference Screenshot](assets/images/reference-screenshot.png) 6 | 7 | ## Notes 8 | 9 | The `adminapi.json` file contains the OpenAPI schema. Please do not make manual changes to that file, since it is synchronized with the latest version using an automated action. Feel free to propose changes to all other files in this repository. 10 | -------------------------------------------------------------------------------- /.github/scripts/extract.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # Input file containing the OpenAPI schema 5 | input_file=$1 6 | 7 | # Output file 8 | output_file=$2 9 | 10 | # Extract keys from "paths" and "components.schemas" 11 | paths=$(jq '.paths | keys' "$input_file") 12 | schemas=$(jq '.components.schemas | keys' "$input_file") 13 | 14 | # Prepare output JSON 15 | output_json="{ \"paths\": $paths, \"schemas\": $schemas }" 16 | 17 | # Pretty-print and save the output JSON to a file 18 | echo "$output_json" | jq '.' > "$output_file" 19 | 20 | echo "Extracted keys from 'paths' and 'components.schemas' and saved to '$output_file'." 21 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "nixpkgs": { 4 | "locked": { 5 | "lastModified": 1673338841, 6 | "narHash": "sha256-8QT5W9uJWR35p8bXK05z0E4xBxN9/BYkAeSSfjvIfts=", 7 | "owner": "nixos", 8 | "repo": "nixpkgs", 9 | "rev": "e1f9232310ff05709058a4d4b20b2c53484140a5", 10 | "type": "github" 11 | }, 12 | "original": { 13 | "owner": "nixos", 14 | "repo": "nixpkgs", 15 | "type": "github" 16 | } 17 | }, 18 | "root": { 19 | "inputs": { 20 | "nixpkgs": "nixpkgs" 21 | } 22 | } 23 | }, 24 | "root": "root", 25 | "version": 7 26 | } 27 | -------------------------------------------------------------------------------- /.github/scripts/find_delta_paths.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | adminapi_paths=$(jq '.paths' adminapi.json) 4 | swag_paths=$(jq '.paths' $1-adminapi.json) 5 | 6 | adminapi_keys=$(echo "$adminapi_paths" | jq 'keys[]') 7 | swag_keys=$(echo "$swag_paths" | jq 'keys[]') 8 | 9 | result_json=$(jq '.' $1-adminapi.json) 10 | 11 | for key in $swag_keys 12 | do 13 | # Check if key is in adminapi keys 14 | if [[ "$adminapi_keys" == *"$key"* ]]; then 15 | # Remove leading and trailing quotes from key 16 | key="${key%\"}" 17 | key="${key#\"}" 18 | 19 | result_json=$(echo "$result_json" | jq "del(.paths.\"$key\")") 20 | fi 21 | done 22 | 23 | echo "$result_json" > $1-adminapi.json 24 | -------------------------------------------------------------------------------- /docs/resources/libraries-sdks/php.md: -------------------------------------------------------------------------------- 1 | # PHP SDK 2 | 3 | The SDKs listed below are third party libraries. We're listing them for your convenience, but their usage comes without any warranty. Shopware is planning to internalize more development of integration kits in the future, but for now we don't want to leave you without solutions. 4 | 5 | Whenever using any of the libraries listed, please respect the license of the individual projects. 6 | 7 | --- 8 | 9 | ## Shopware PHP SDK 10 | 11 | https://github.com/vienthuong/shopware-php-sdk 12 | 13 | Comes with a nice querying syntax, closely resembling the one from the internal DAL. Allows for Server-to-Server communication using Shopware's Admin API. 14 | 15 | Maintained by: [Thuong Le](https://github.com/vienthuong) 16 | 17 | --- 18 | 19 | -------------------------------------------------------------------------------- /docs/resources/libraries-sdks/python.md: -------------------------------------------------------------------------------- 1 | # Python SDK 2 | 3 | The SDKs listed below are third party libraries. We're listing them for your convenience, but their usage comes without any warranty. Shopware is planning to internalize more development of integration kits in the future, but for now we don't want to leave you without solutions. 4 | 5 | Whenever using any of the libraries listed, please respect the license of the individual projects. 6 | 7 | --- 8 | 9 | ## Python API Client 10 | 11 | https://github.com/bitranox/lib_shopware6_api_base 12 | 13 | This library provides a low-level abstraction layer that helps with authentication and requests towards the Admin API within Python environments. 14 | 15 | Maintained by: [Robert Nowotny](https://github.com/bitranox) 16 | 17 | --- 18 | 19 | -------------------------------------------------------------------------------- /.github/workflows/schedule_versions.yml: -------------------------------------------------------------------------------- 1 | name: Schedule version PRs 2 | 3 | on: 4 | workflow_dispatch: 5 | schedule: 6 | - cron: 0 9 */1 * * 7 | 8 | env: 9 | SHOPWARE_VERSION: 'trunk' 10 | PHP_VERSION: '8.2' 11 | 12 | jobs: 13 | vars: 14 | runs-on: ubuntu-22.04 15 | outputs: 16 | SHOPWARE_VERSION: ${{ env.SHOPWARE_VERSION }} 17 | PHP_VERSION: ${{ env.PHP_VERSION }} 18 | steps: 19 | - run: echo "Exposing env vars" 20 | generate-trunk: 21 | needs: vars 22 | uses: ./.github/workflows/base_schema.yml 23 | with: 24 | shopware_version: ${{ needs.vars.outputs.SHOPWARE_VERSION }} 25 | php_version: ${{ needs.vars.outputs.PHP_VERSION }} 26 | secrets: inherit 27 | 28 | generate-commercial-trunk: 29 | needs: vars 30 | uses: ./.github/workflows/plugin_commercial_schema.yml 31 | with: 32 | shopware_version: ${{ needs.vars.outputs.SHOPWARE_VERSION }} 33 | php_version: ${{ needs.vars.outputs.PHP_VERSION }} 34 | secrets: inherit 35 | 36 | generate-digitalsalesroom-trunk: 37 | needs: vars 38 | uses: ./.github/workflows/plugin_digitalsalesroom_schema.yml 39 | with: 40 | shopware_version: ${{ needs.vars.outputs.SHOPWARE_VERSION }} 41 | php_version: ${{ needs.vars.outputs.PHP_VERSION }} 42 | secrets: inherit 43 | -------------------------------------------------------------------------------- /docs/concepts/endpoint-structure/reading-entities.md: -------------------------------------------------------------------------------- 1 | # Reading entities 2 | 3 | The Admin API is designed in such a way that all entities of the system can be read in the same way. Once an entity is registered in the system, it can be written and read via API - this also applies to your custom entities. The appropriate routes for the entity are generated automatically and follow the REST pattern. 4 | 5 | A list of all entities available for read operations can be found in the [Entity Reference](../../resources/entity-reference.md). 6 | 7 | > **Example** 8 | > 9 | > * The `ManufacturerEntity` is registered as `product_manufacturer` in the system and can be read through `api/product-manufacturer`. 10 | > * The `ProductEntity` has an association with the property name `manufacturer`, which refers to the `ManufacturerEntity`. 11 | > * The manufacturer of a product can then be read over `api/product/{productId}/manufacturer`. 12 | 13 | If you are unsure what the name of your entity is, see the definition of the entity: 14 | 15 | `final public const ENTITY_NAME = 'product_manufacturer';` 16 | 17 | ## Generated Endpoints 18 | 19 | For an entity object, the system automatically creates the following routes through which the entity object can be read: 20 | 21 | | Name | Method | Route | Usage | 22 | | :--- | :--- | :--- | :--- | 23 | | api.customer\_group.list | GET | /api/customer-group | Fetch a list of entities | 24 | | api.customer\_group.detail | GET | /api/customer-group/{id} | Fetch a single entity | 25 | | api.customer\_group.search | POST | /api/search/customer-group | Perform a search using a [search criteria](#search-endpoint) | 26 | | api.customer\_group.search-ids | POST | /api/search-ids/customer-group | Perform a search using a [search criteria](#search-endpoint), but fetch only matching ids | 27 | 28 | ## Search Endpoint 29 | 30 | The Admin API supports a wide range of filtering, aggregation and sorting capabilities. However, according to the REST definition, data should only be read via GET, we have provided the `/api/search/*` route for this. 31 | 32 | These endpoints accept a search criteria input: 33 | 34 | ```json json_schema 35 | { 36 | "$ref": "../../../adminapi.json#/components/schemas/Criteria" 37 | } 38 | ``` 39 | -------------------------------------------------------------------------------- /.github/workflows/manual_versioning.yml: -------------------------------------------------------------------------------- 1 | name: Manual version PRs 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | shopware_version: 7 | description: "Shopware version" 8 | required: true 9 | type: string 10 | php_version: 11 | description: "PHP version" 12 | required: false 13 | type: string 14 | default: "8.2" 15 | trigger_default_schema: 16 | description: "Trigger schema" 17 | required: false 18 | type: boolean 19 | default: true 20 | trigger_commercial_schema: 21 | description: "Trigger commercial schema" 22 | required: false 23 | type: boolean 24 | default: true 25 | trigger_digitalsalesroom_schema: 26 | description: "Trigger digitalsalesroom schema" 27 | required: false 28 | type: boolean 29 | default: true 30 | trigger_customproducts_schema: 31 | description: "Trigger custom products schema" 32 | required: false 33 | type: boolean 34 | default: true 35 | 36 | jobs: 37 | generate-trunk: 38 | if: ${{ inputs.trigger_default_schema }} 39 | uses: ./.github/workflows/base_schema.yml 40 | with: 41 | shopware_version: ${{ inputs.shopware_version }} 42 | php_version: ${{ inputs.php_version }} 43 | secrets: inherit 44 | 45 | generate-commercial-trunk: 46 | if: ${{ inputs.trigger_commercial_schema }} 47 | uses: ./.github/workflows/plugin_commercial_schema.yml 48 | with: 49 | shopware_version: ${{ inputs.shopware_version }} 50 | php_version: ${{ inputs.php_version }} 51 | secrets: inherit 52 | 53 | generate-digitalsalesroom-trunk: 54 | if: ${{ inputs.trigger_digitalsalesroom_schema }} 55 | uses: ./.github/workflows/plugin_digitalsalesroom_schema.yml 56 | with: 57 | shopware_version: ${{ inputs.shopware_version }} 58 | php_version: ${{ inputs.php_version }} 59 | secrets: inherit 60 | generate-customproducts-trunk: 61 | if: ${{ inputs.trigger_customproducts_schema }} 62 | uses: ./.github/workflows/plugin_customproducts_schema.yml 63 | with: 64 | shopware_version: ${{ inputs.shopware_version }} 65 | php_version: ${{ inputs.php_version }} 66 | secrets: inherit 67 | -------------------------------------------------------------------------------- /docs/guides/quick-start/04-document-management.md: -------------------------------------------------------------------------------- 1 | --- 2 | stoplight-id: 3be386a26c0f9 3 | --- 4 | 5 | # Document Management 6 | 7 | One can use documents to send the invoice, delivery notes, packing slips, etc. Already defined document types can be fetched from : 8 | 9 | ``` markdown 10 | GET /api/document-type 11 | ``` 12 | 13 | ## Creating a document type 14 | 15 | You can create a document by its purpose - for example, a note for returned items using a simple payload. 16 | 17 | ```sample http 18 | { 19 | "method": "post", 20 | "url": "http://localhost/api/document-type", 21 | "headers": { 22 | "Content-Type": "application/json", 23 | "Accept": "application/json", 24 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 25 | }, 26 | "body": { 27 | "name": "return note", 28 | "technicalName": "return-note" 29 | } 30 | } 31 | ``` 32 | 33 | If documents are assigned to `global,` they can be used on any sales channel. This can be defined in the `document_base_config` entity as shown below: 34 | 35 | ```sample http 36 | { 37 | "method": "post", 38 | "url": "http://localhost/api/document-base-config", 39 | "headers": { 40 | "Content-Type": "application/json", 41 | "Accept": "application/json", 42 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 43 | }, 44 | "body": { 45 | "documentTypeId": "9cc669c406b441e1b7af035552db138f", 46 | "name": "return note", 47 | "global": true 48 | } 49 | } 50 | ``` 51 | 52 | These documents are associated with order events. The below endpoint creates a document of invoice type for a particular order. 53 | 54 | ```sample http 55 | { 56 | "method": "post", 57 | "url": "http://localhost/api/_action/order/document/invoice/create", 58 | "headers": { 59 | "Content-Type": "application/json", 60 | "Accept": "application/json", 61 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 62 | }, 63 | "body": { 64 | "orderId": "d84bbaaa3423495e8c98eef1444db7d0", 65 | "type": "string", 66 | "fileType": "pdf", 67 | "static": false, 68 | "referencedDocumentId": null, 69 | "config": {}, 70 | "sent": true 71 | } 72 | } 73 | ``` 74 | 75 | While placing an order, during order transaction or order delivery, you have the option to set the `sent` parameter to `true`. It is a boolean flag that determines whether to skip the creation of documents that have already been marked as sent while processing orders. 76 | 77 | ## Download a document 78 | 79 | The below route allows you to download a document as a PDF. The document is followed by its ID and deeplink code. 80 | 81 | ```sample http 82 | { 83 | "method": "post", 84 | "url": "http://localhost/api/_action/document/d01c4e3cc8ef49abbdb094a0d8c0547b/XdcfdoQITWimRreZFf6yMIcXfe3gl1op", 85 | "headers": { 86 | "Content-Type": "application/json", 87 | "Accept": "application/json", 88 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 89 | } 90 | } 91 | ``` 92 | -------------------------------------------------------------------------------- /.github/workflows/plugin_commercial_schema.yml: -------------------------------------------------------------------------------- 1 | name: Update Commercial Store API 2 | 3 | on: 4 | workflow_call: 5 | inputs: 6 | shopware_version: 7 | description: "Shopware version" 8 | required: true 9 | type: string 10 | php_version: 11 | description: "PHP version" 12 | required: false 13 | type: string 14 | 15 | env: 16 | PLUGIN_NAME: SwagCommercial 17 | PLUGIN_URL: gitlab.shopware.com/shopware/6/product/commercial.git 18 | 19 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 20 | jobs: 21 | vars: 22 | runs-on: ubuntu-22.04 23 | outputs: 24 | PLUGIN_NAME: ${{ env.PLUGIN_NAME }} 25 | PLUGIN_URL: ${{ env.PLUGIN_URL }} 26 | steps: 27 | - run: echo "Exposing env vars" 28 | # This workflow contains a single job called "build" 29 | generate-schema: 30 | needs: vars 31 | uses: shopware/docs-ci/.github/workflows/generate_schema.yml@main 32 | with: 33 | schema_flags: "" 34 | schema_file: ${{ needs.vars.outputs.PLUGIN_NAME }}-adminapi.json 35 | plugin_name: ${{ needs.vars.outputs.PLUGIN_NAME }} 36 | plugin_url: ${{ needs.vars.outputs.PLUGIN_URL }} 37 | shopware_version: ${{ inputs.shopware_version }} 38 | php_version: ${{ inputs.php_version }} 39 | secrets: inherit 40 | open-pr: 41 | name: "Open a pull request" 42 | runs-on: ubuntu-latest 43 | needs: [generate-schema,vars] 44 | steps: 45 | - name: Checkout 46 | uses: actions/checkout@v4 47 | 48 | - name: download api schema 49 | uses: actions/download-artifact@v4 50 | with: 51 | name: ${{needs.generate-schema.outputs.api_schema}} 52 | 53 | - name: install yq 54 | uses: cachix/install-nix-action@v18 55 | 56 | - name: Prettify 57 | run: | 58 | sudo apt-get update 59 | sudo apt-get install -y moreutils 60 | jq . ${{ needs.vars.outputs.PLUGIN_NAME }}-adminapi.json | sponge ${{ needs.vars.outputs.PLUGIN_NAME }}-adminapi.json 61 | ./.github/scripts/find_delta_paths.sh ${{ needs.vars.outputs.PLUGIN_NAME }} 62 | 63 | - name: Extract summary 64 | run: | 65 | chmod +x ./.github/scripts/extract.sh 66 | ./.github/scripts/extract.sh ${{ needs.vars.outputs.PLUGIN_NAME }}-adminapi.json ${{ needs.vars.outputs.PLUGIN_NAME }}-adminapi.summary.json 67 | 68 | - name: Create DSR PR 69 | uses: peter-evans/create-pull-request@v6 70 | with: 71 | add-paths: | 72 | ${{ needs.vars.outputs.PLUGIN_NAME }}-adminapi.json 73 | ${{ needs.vars.outputs.PLUGIN_NAME }}-adminapi.summary.json 74 | author: shopwareBot 75 | committer: shopwareBot 76 | assignees: Isengo1989, sushmangupta, bojanrajh 77 | branch: ${{ needs.vars.outputs.PLUGIN_NAME }}-schema-update 78 | delete-branch: true 79 | title: 'Update ${{ needs.vars.outputs.PLUGIN_NAME }} admin API schema' 80 | -------------------------------------------------------------------------------- /.github/workflows/plugin_customproducts_schema.yml: -------------------------------------------------------------------------------- 1 | name: Update Custom Products Admin API 2 | 3 | on: 4 | workflow_call: 5 | inputs: 6 | shopware_version: 7 | description: "Shopware version" 8 | required: true 9 | type: string 10 | php_version: 11 | description: "PHP version" 12 | required: false 13 | type: string 14 | 15 | env: 16 | PLUGIN_NAME: SwagCustomizedProducts 17 | PLUGIN_URL: gitlab.shopware.com/shopware/6/services/customized-product.git 18 | 19 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 20 | jobs: 21 | vars: 22 | runs-on: ubuntu-22.04 23 | outputs: 24 | PLUGIN_NAME: ${{ env.PLUGIN_NAME }} 25 | PLUGIN_URL: ${{ env.PLUGIN_URL }} 26 | COMPOSER_PACKAGES: ${{ env.COMPOSER_PACKAGES }} 27 | steps: 28 | - run: echo "Exposing env vars" 29 | # This workflow contains a single job called "build" 30 | generate-schema: 31 | needs: vars 32 | uses: shopware/docs-ci/.github/workflows/generate_schema.yml@main 33 | with: 34 | schema_flags: "" 35 | schema_file: ${{ needs.vars.outputs.PLUGIN_NAME }}-adminapi.json 36 | plugin_name: ${{ needs.vars.outputs.PLUGIN_NAME }} 37 | plugin_url: ${{ needs.vars.outputs.PLUGIN_URL }} 38 | composer_packages: ${{ needs.vars.outputs.COMPOSER_PACKAGES }} 39 | shopware_version: ${{ inputs.shopware_version }} 40 | php_version: ${{ inputs.php_version }} 41 | secrets: 42 | DEPLOY_USER: ${{ secrets.CUSTOMPRODUCTS_DEPLOY_USER }} 43 | DEPLOY_TOKEN: ${{ secrets.CUSTOMPRODUCTS_DEPLOY_TOKEN }} 44 | 45 | open-pr: 46 | name: "Open a pull request" 47 | runs-on: ubuntu-latest 48 | needs: [generate-schema,vars] 49 | steps: 50 | - name: Checkout 51 | uses: actions/checkout@v4 52 | 53 | - name: download api schema 54 | uses: actions/download-artifact@v4 55 | with: 56 | name: ${{needs.generate-schema.outputs.api_schema}} 57 | 58 | - name: install yq 59 | uses: cachix/install-nix-action@v18 60 | 61 | - name: Prettify 62 | run: | 63 | sudo apt-get update 64 | sudo apt-get install -y moreutils 65 | jq . ${{ needs.vars.outputs.PLUGIN_NAME }}-adminapi.json | sponge ${{ needs.vars.outputs.PLUGIN_NAME }}-adminapi.json 66 | ./.github/scripts/find_delta_paths.sh ${{ needs.vars.outputs.PLUGIN_NAME }} 67 | 68 | - name: Extract summary 69 | run: | 70 | chmod +x ./.github/scripts/extract.sh 71 | ./.github/scripts/extract.sh ${{ needs.vars.outputs.PLUGIN_NAME }}-adminapi.json ${{ needs.vars.outputs.PLUGIN_NAME }}-adminapi.summary.json 72 | 73 | - name: Create DSR PR 74 | uses: peter-evans/create-pull-request@v6 75 | with: 76 | add-paths: | 77 | ${{ needs.vars.outputs.PLUGIN_NAME }}-adminapi.json 78 | ${{ needs.vars.outputs.PLUGIN_NAME }}-adminapi.summary.json 79 | author: shopwareBot 80 | committer: shopwareBot 81 | assignees: Isengo1989, sushmangupta, bojanrajh 82 | branch: ${{ needs.vars.outputs.PLUGIN_NAME }}-schema-update 83 | delete-branch: true 84 | title: 'Update ${{ needs.vars.outputs.PLUGIN_NAME }} admin API schema' -------------------------------------------------------------------------------- /.github/workflows/plugin_digitalsalesroom_schema.yml: -------------------------------------------------------------------------------- 1 | name: Update Digital Sales Room Store API 2 | 3 | on: 4 | workflow_call: 5 | inputs: 6 | shopware_version: 7 | description: "Shopware version" 8 | required: true 9 | type: string 10 | php_version: 11 | description: "PHP version" 12 | required: false 13 | type: string 14 | 15 | env: 16 | PLUGIN_NAME: SwagDigitalSalesRooms 17 | PLUGIN_URL: gitlab.shopware.com/shopware/6/services/swagdigitalsalesrooms.git 18 | COMPOSER_PACKAGES: shopware-pwa/shopware-pwa dev-master symfony/mercure ^0.6.2 spatie/icalendar-generator ^2.5 nesbot/carbon ^3.0.0-rc.1@rc 19 | 20 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 21 | jobs: 22 | vars: 23 | runs-on: ubuntu-22.04 24 | outputs: 25 | PLUGIN_NAME: ${{ env.PLUGIN_NAME }} 26 | PLUGIN_URL: ${{ env.PLUGIN_URL }} 27 | COMPOSER_PACKAGES: ${{ env.COMPOSER_PACKAGES }} 28 | steps: 29 | - run: echo "Exposing env vars" 30 | # This workflow contains a single job called "build" 31 | generate-schema: 32 | needs: vars 33 | uses: shopware/docs-ci/.github/workflows/generate_schema.yml@main 34 | with: 35 | schema_flags: "" 36 | schema_file: ${{ needs.vars.outputs.PLUGIN_NAME }}-adminapi.json 37 | plugin_name: ${{ needs.vars.outputs.PLUGIN_NAME }} 38 | plugin_url: ${{ needs.vars.outputs.PLUGIN_URL }} 39 | composer_packages: ${{ needs.vars.outputs.COMPOSER_PACKAGES }} 40 | shopware_version: ${{ inputs.shopware_version }} 41 | php_version: ${{ inputs.php_version }} 42 | secrets: 43 | DEPLOY_USER: ${{ secrets.DIGITALSALESROOM_DEPLOY_USER }} 44 | DEPLOY_TOKEN: ${{ secrets.DIGITALSALESROOM_DEPLOY_TOKEN }} 45 | DAILY_CO_API_KEY: ${{ secrets.DAILY_CO_API_KEY }} 46 | open-pr: 47 | name: "Open a pull request" 48 | runs-on: ubuntu-latest 49 | needs: [generate-schema,vars] 50 | steps: 51 | - name: Checkout 52 | uses: actions/checkout@v4 53 | 54 | - name: download api schema 55 | uses: actions/download-artifact@v4 56 | with: 57 | name: ${{needs.generate-schema.outputs.api_schema}} 58 | 59 | - name: install yq 60 | uses: cachix/install-nix-action@v18 61 | 62 | - name: Prettify 63 | run: | 64 | sudo apt-get update 65 | sudo apt-get install -y moreutils 66 | jq . ${{ needs.vars.outputs.PLUGIN_NAME }}-adminapi.json | sponge ${{ needs.vars.outputs.PLUGIN_NAME }}-adminapi.json 67 | ./.github/scripts/find_delta_paths.sh ${{ needs.vars.outputs.PLUGIN_NAME }} 68 | 69 | - name: Extract summary 70 | run: | 71 | chmod +x ./.github/scripts/extract.sh 72 | ./.github/scripts/extract.sh ${{ needs.vars.outputs.PLUGIN_NAME }}-adminapi.json ${{ needs.vars.outputs.PLUGIN_NAME }}-adminapi.summary.json 73 | 74 | - name: Create DSR PR 75 | uses: peter-evans/create-pull-request@v6 76 | with: 77 | add-paths: | 78 | ${{ needs.vars.outputs.PLUGIN_NAME }}-adminapi.json 79 | ${{ needs.vars.outputs.PLUGIN_NAME }}-adminapi.summary.json 80 | author: shopwareBot 81 | committer: shopwareBot 82 | assignees: Isengo1989, sushmangupta, bojanrajh 83 | branch: ${{ needs.vars.outputs.PLUGIN_NAME }}-schema-update 84 | delete-branch: true 85 | title: 'Update ${{ needs.vars.outputs.PLUGIN_NAME }} admin API schema' -------------------------------------------------------------------------------- /.github/workflows/base_schema.yml: -------------------------------------------------------------------------------- 1 | name: Update Admin API 2 | 3 | on: 4 | workflow_call: 5 | inputs: 6 | shopware_version: 7 | description: "Shopware version" 8 | required: true 9 | type: string 10 | php_version: 11 | description: "PHP version" 12 | required: false 13 | type: string 14 | 15 | jobs: 16 | 17 | save-file: 18 | name: "Save file" 19 | runs-on: ubuntu-latest 20 | steps: 21 | - name: Checkout repo 22 | uses: actions/checkout@v4 23 | - shell: bash 24 | run: | 25 | cp adminapi.json adminapi-original.json 26 | - name: Upload original file 27 | uses: actions/upload-artifact@v4 28 | with: 29 | name: original-file 30 | path: adminapi-original.json 31 | # This workflow contains a single job called "build" 32 | generate-schema: 33 | uses: shopware/docs-ci/.github/workflows/generate_schema.yml@main 34 | with: 35 | schema_flags: "" 36 | schema_file: adminapi.json 37 | shopware_version: ${{ inputs.shopware_version }} 38 | php_version: ${{ inputs.php_version }} 39 | secrets: inherit 40 | 41 | open-pr: 42 | name: "Open a pull request" 43 | runs-on: ubuntu-latest 44 | needs: [generate-schema] 45 | env: 46 | FILE_DIFFERENCE: 0 47 | BRANCH_NAME: ${{ github.head_ref || github.ref_name }} 48 | steps: 49 | - name: Checkout 50 | uses: actions/checkout@v4 51 | 52 | - name: download api schema 53 | uses: actions/download-artifact@v4 54 | with: 55 | name: ${{needs.generate-schema.outputs.api_schema}} 56 | 57 | - name: install yq 58 | uses: cachix/install-nix-action@v18 59 | 60 | - name: Add custom descriptions 61 | run: | 62 | for k in $(yq '. | keys | .[]' descriptions.yml); do 63 | newDescription=$(yq ".\"$k\"" descriptions.yml); 64 | # Indent 4; output as json; edit in place 65 | yq -I 4 -o json -i "$k.description = \"${newDescription}\"" adminapi.json 66 | done 67 | 68 | for k in $(yq '. | keys | .[]' enhance.yml); do 69 | newData=$(yq ".\"${k}\"" enhance.yml); 70 | # escape all keys by default 71 | j=$(echo "$k" | sed -r 's/[.]+/"."/g') 72 | # remove first extra quote 73 | j=${j#*\"} 74 | # add one extra quote at the end 75 | yq -I 4 -o json -i "${j}\" = \"${newData}\"" adminapi.json 76 | done 77 | 78 | - name: Download original file 79 | uses: actions/download-artifact@v4 80 | with: 81 | name: original-file 82 | 83 | - name: Prettify 84 | run: | 85 | sudo apt-get update 86 | sudo apt-get install -y moreutils 87 | jq . adminapi.json | sponge adminapi.json 88 | cmp <(sort adminapi.json) <(sort adminapi-original.json) || echo "FILE_DIFFERENCE=1" >> $GITHUB_ENV 89 | rm adminapi-original.json 90 | 91 | - name: Extract summary 92 | run: | 93 | chmod +x ./.github/scripts/extract.sh 94 | ./.github/scripts/extract.sh adminapi.json adminapi.summary.json 95 | 96 | - name: Create PR 97 | uses: peter-evans/create-pull-request@v6 98 | with: 99 | add-paths: | 100 | adminapi.json 101 | adminapi.summary.json 102 | author: shopwareBot 103 | committer: shopwareBot 104 | assignees: sushmangupta, Isengo1989, bojanrajh 105 | branch: "schema-update-${{ env.BRANCH_NAME }}" 106 | delete-branch: true 107 | title: 'Update ${{ env.BRANCH_NAME }} admin API schema' 108 | -------------------------------------------------------------------------------- /toc.json: -------------------------------------------------------------------------------- 1 | { 2 | "items": [ 3 | { 4 | "type": "divider", 5 | "title": "Guides" 6 | }, 7 | { 8 | "type": "item", 9 | "title": "Introduction", 10 | "uri": "docs/guides/quick-start/01-introduction.md" 11 | }, 12 | { 13 | "type": "item", 14 | "title": "Product Management", 15 | "uri": "docs/guides/quick-start/02-product-management.md" 16 | }, 17 | { 18 | "type": "item", 19 | "title": "Media Management", 20 | "uri": "docs/guides/quick-start/03-media-handling.md" 21 | }, 22 | { 23 | "type": "item", 24 | "title": "Document Management", 25 | "uri": "docs/guides/quick-start/04-document-management.md" 26 | }, 27 | { 28 | "type": "item", 29 | "title": "Order Management", 30 | "uri": "docs/guides/quick-start/05-order-management.md" 31 | }, 32 | { 33 | "type": "item", 34 | "title": "CMS Management", 35 | "uri": "docs/guides/quick-start/06-cms-handling.md" 36 | }, 37 | { 38 | "type": "divider", 39 | "title": "Concepts" 40 | }, 41 | { 42 | "type": "item", 43 | "title": "Authentication & Authorisation", 44 | "uri": "docs/concepts/authentication-authorisation.md", 45 | "slug": "authentication" 46 | }, 47 | { 48 | "type": "item", 49 | "title": "Request & Response Structure", 50 | "uri": "docs/concepts/request-response-structure.md" 51 | }, 52 | { 53 | "type": "group", 54 | "title": "Request & Response Structure", 55 | "items": [ 56 | { 57 | "type": "item", 58 | "title": "Overview", 59 | "uri": "docs/concepts/endpoint-structure/request-response-structure.md", 60 | "slug": "request-and-response-structure" 61 | }, 62 | { 63 | "type": "item", 64 | "title": "Reading Entities", 65 | "uri": "docs/concepts/endpoint-structure/reading-entities.md" 66 | }, 67 | { 68 | "type": "group", 69 | "title": "Writing Entities", 70 | "items": [ 71 | { 72 | "type": "item", 73 | "title": "Overview", 74 | "uri": "docs/concepts/endpoint-structure/writing-entities/README.md" 75 | }, 76 | { 77 | "type": "item", 78 | "title": "Product Data", 79 | "uri": "docs/concepts/endpoint-structure/writing-entities/product-data.md" 80 | }, 81 | { 82 | "type": "item", 83 | "title": "Associations", 84 | "uri": "docs/concepts/endpoint-structure/writing-entities/associations.md" 85 | }, 86 | { 87 | "type": "item", 88 | "title": "Bulk Payloads", 89 | "uri": "docs/concepts/endpoint-structure/writing-entities/bulk-payloads.md" 90 | } 91 | ] 92 | } 93 | ] 94 | }, 95 | { 96 | "type": "divider", 97 | "title": "Resources" 98 | }, 99 | { 100 | "type": "item", 101 | "title": "Entity Reference", 102 | "uri": "docs/resources/entity-reference.md" 103 | }, 104 | { 105 | "type": "group", 106 | "title": "Libraries & SDKs", 107 | "items": [ 108 | { 109 | "type": "item", 110 | "title": "PHP", 111 | "uri": "docs/resources/libraries-sdks/php.md" 112 | }, 113 | { 114 | "type": "item", 115 | "title": "Python", 116 | "uri": "docs/resources/libraries-sdks/python.md" 117 | } 118 | ] 119 | }, 120 | { 121 | "type": "divider", 122 | "title": "Core" 123 | }, 124 | { 125 | "type": "item", 126 | "title": "Endpoints", 127 | "uri": "adminapi.json" 128 | }, 129 | { 130 | "type": "divider", 131 | "title": "Commercial" 132 | }, 133 | { 134 | "type": "item", 135 | "title": "Endpoints", 136 | "uri": "SwagCommercial-adminapi.json" 137 | }, 138 | { 139 | "type": "divider", 140 | "title": "Digital Sales Rooms" 141 | }, 142 | { 143 | "type": "item", 144 | "title": "Endpoints", 145 | "uri": "SwagDigitalSalesRooms-adminapi.json" 146 | }, 147 | { 148 | "type": "divider", 149 | "title": "Customized Products" 150 | }, 151 | { 152 | "type": "item", 153 | "title": "Endpoints", 154 | "uri": "SwagCustomizedProducts-adminapi.json" 155 | } 156 | ] 157 | } 158 | -------------------------------------------------------------------------------- /docs/guides/quick-start/01-introduction.md: -------------------------------------------------------------------------------- 1 | --- 2 | stoplight-id: twpxvnspkg3yu 3 | --- 4 | 5 | # Quick Start Guide 6 | 7 | ## Overview 8 | 9 | The Shopware Admin API allows web services to perform administrative tasks. This guide is designed to help you understand the Admin API, its endpoints, and its usage. 10 | 11 | * [Authentication as API user](#authentication-and-setup) 12 | 13 | * [Product management](02-product-management.md) 14 | 15 | * Product creation 16 | 17 | * Categories 18 | 19 | * Dynamic product groups 20 | 21 | * Product reviews 22 | 23 | * Cross-selling 24 | 25 | * Price 26 | 27 | * [Media management](03-media-handling.md) 28 | 29 | * [Document management](04-document-management.md) 30 | 31 | * [Order management](05-order-management.md) 32 | 33 | * Create order 34 | 35 | * Line item 36 | 37 | * Order state handling 38 | 39 | * Refund payment 40 | 41 | * [CMS management](06-cms-handling.md) 42 | 43 | * Creation of layout 44 | 45 | * Assignment of layout to a category 46 | 47 | It is useful to use an API client like Postman or Insomnia to follow this guide. 48 | 49 | ## General 50 | 51 | The Admin API has a base route that is always relative to your Shopware instance host. Note that it might differ from your sales channel domain. Let us assume your Shopware host is: 52 | 53 | ``` 54 | https://shop.example.com/ 55 | ``` 56 | 57 | Then your Admin API base route will be: 58 | 59 | ``` 60 | https://shop.example.com/api/ 61 | ``` 62 | 63 | The Admin API offers a variety of functionalities referred to as endpoints or nodes, where each has its own route. Refer to [endpoint structure](https://shopware.stoplight.io/docs/admin-api/ZG9jOjEyMzA1ODA5-endpoint-structure) for more details. The endpoints mentioned subsequently are always relative to the API base route. 64 | 65 | ## Authentication and Setup 66 | 67 | All REST Admin API queries require a valid Shopware access token. The Admin API uses the OAuth 2.0 standard to authenticate users and requires you to obtain an access token to confirm your identity for every server request. 68 | 69 | OAuth 2.0 defines various user authentication types called application grant types. We recommend only using the Password credentials grant type for all client integrations, which grants client applications to perform administrative actions. 70 | 71 | ### Configure OAuth in a REST client 72 | 73 | A typical Admin API request, including headers, will look as shown below: 74 | 75 | ```json http 76 | { 77 | "method": "post", 78 | "url": "http://localhost/api/oauth/token", 79 | "headers": { 80 | "Content-Type": "application/json", 81 | "Accept": "application/json" 82 | }, 83 | "body":{ 84 | "client_id": "administration", 85 | "grant_type": "password", 86 | "scope": "write", 87 | "username": "your.username@shopware.com", 88 | "password": "your.password@123" 89 | } 90 | } 91 | ``` 92 | 93 | Once you have obtained the access token, simply add it to the `Authorization` header as a Bearer token. 94 | 95 | Many REST clients also come with built-in functionality to support the OAuth grant flows. 96 | 97 | In Insomnia or Postman, just select **OAuth 2.0** in the *Authorization* tab of your request and enter the following configuration: 98 | 99 | | Config | Value | 100 | |--------------------- | ------------------------------------------------- | 101 | | **Grant Type** | Password Credentials | 102 | | **Username** | Admin user name | 103 | | **Password** | Admin user password | 104 | | **Access Token URL** | `https://replace-with-your-host/api/oauth/token` | 105 | | **Client ID** | `administration` | 106 | 107 | Now that you have authenticated, you can perform your first request to obtain your Shopware version. 108 | 109 | ```json http 110 | { 111 | "method": "get", 112 | "url": "http://localhost/api/_info/version", 113 | "headers": { 114 | "Content-Type": "application/json", 115 | "Accept": "application/json", 116 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 117 | } 118 | } 119 | ``` 120 | 121 | Below is the response: 122 | 123 | ``` 124 | { 125 | "version": "6.5.3.0" 126 | } 127 | ``` 128 | 129 | Depending on your setup, the integration type differs, hence the process of [obtaining the access token](https://shopware.stoplight.io/docs/admin-api/ZG9jOjEwODA3NjQx-authentication#obtain-an-access-token). 130 | -------------------------------------------------------------------------------- /docs/concepts/authentication-authorisation.md: -------------------------------------------------------------------------------- 1 | # Authentication 2 | 3 | The Admin API uses the [OAuth 2.0](https://oauth.net/2/) standard to authenticate users. In short, OAuth 2.0 requires you to obtain an access token which you will have to include in every subsequent request so the server can confirm your identity. 4 | 5 | ## Grant Types 6 | 7 | OAuth 2.0 defines various ways that users can authenticate, so-called **application grant types**. The Admin API supports two grant types or -flows: 8 | 9 | * Client Credentials Grant 10 | * Resource Owner Password Grant 11 | * \(Refresh Token Grant\) 12 | 13 | Not sure which grant type to use? Read on below. 14 | 15 | ### Client Credentials 16 | 17 | Per standard, the client credentials grant type should be used for machine-to-machine communications, such as CLI jobs or automated services. Once an access token has been obtained, it remains valid for 10 minutes. 18 | 19 | > It requires the setup of an [integration](https://docs.shopware.com/en/shopware-6-en/settings/system/integrationen?category=shopware-6-en/settings/system) and two credentials - an **Access key ID** and a **Secret access key**. 20 | 21 | ### Resource Owner Password 22 | 23 | The resource owner password credentials grant is used by our admin panel. It identifies the API user based on a **username** and a **password** in exchange for an access token with a lifetime of 10 minutes and a refresh token. We recommend to only use this grant flow for client applications that should perform administrative actions and require a user-based authentication. 24 | 25 | > It requires an [admin user](https://docs.shopware.com/en/shopware-6-en/settings/system/user?category=shopware-6-en/settings/system#new-user) to be set up. 26 | 27 | 28 | ### Refresh Token 29 | 30 | This grant is only available, when a preceding authentication with the resource owner password grant type has been performed. The **refresh token** obtained during the initial authentication can be exchanged for another short-lived \(10 minutes\) access token. 31 | 32 | ## Obtain an access token 33 | 34 | In order to obtain an access token, perform one of the following requests, depending on your setup and grant type. 35 | 36 | ### Integration (Client Credentials Grant Type) 37 | ```sample http 38 | { 39 | "method": "POST", 40 | "url": "http://localhost/api/oauth/token", 41 | "headers": { 42 | "Content-Type": "application/json", 43 | "Accept": "application/json", 44 | }, 45 | "body": { 46 | "grant_type": "client_credentials", 47 | "client_id": "", 48 | "client_secret": "" 49 | } 50 | } 51 | ``` 52 | 53 | which will return 54 | 55 | ```javascript 56 | { 57 | "token_type": "Bearer", 58 | "expires_in": 600, 59 | "access_token": "xxxxxxxxxxxxxx" 60 | } 61 | ``` 62 | 63 | ### Username and Password (Password Grant Type) 64 | ```sample http 65 | { 66 | "method": "POST", 67 | "url": "http://localhost/api/oauth/token", 68 | "headers": { 69 | "Content-Type": "application/json", 70 | "Accept": "application/json", 71 | }, 72 | "body": { 73 | "client_id": "administration", 74 | "grant_type": "password", 75 | "scopes": "write", 76 | "username": "", 77 | "password": "" 78 | } 79 | } 80 | ``` 81 | 82 | which will return 83 | 84 | ```javascript 85 | { 86 | "token_type": "Bearer", 87 | "expires_in": 600, 88 | "access_token": "xxxxxxxxxxxxxx", 89 | "refresh_token": "token" 90 | } 91 | ``` 92 | 93 | Make sure to also persist the `refresh_token` for subsequent authentications using the refresh token grant. 94 | 95 | ### Refresh Token 96 | ```sample http 97 | { 98 | "method": "POST", 99 | "url": "http://localhost/api/oauth/token", 100 | "headers": { 101 | "Content-Type": "application/json", 102 | "Accept": "application/json", 103 | }, 104 | "body": { 105 | "grant_type": "refresh_token", 106 | "client_id": "", 107 | "refresh_token": "" 108 | } 109 | } 110 | ``` 111 | 112 | which will return 113 | 114 | ```javascript 115 | { 116 | "token_type": "Bearer", 117 | "expires_in": 600, 118 | "access_token": "xxxxxxxxxxxxxx", 119 | "refresh_token": "token" 120 | } 121 | ``` 122 | 123 | ## Use the access token 124 | 125 | Once you've obtained an access token, simply provide it in your requests `Authorization` header as a Bearer token and you're ready to go. 126 | 127 | ```yaml 128 | // GET /api/product/b7d2554b0ce847cd82f3ac9bd1c0dfad 129 | 130 | Host: shop.example.com 131 | Content-Type: application/json 132 | Authorization: Bearer eyJ0.... <- this is where your access token goes 133 | ``` 134 | 135 | ## Configure OAuth in a REST client 136 | 137 | Many REST clients, such as Postman or Insomnia come with built-in functionality to support the OAuth grant flows. 138 | 139 | In Insomnia, just select **OAuth 2** in the *Authentication* tab of your request and enter the following configuration: 140 | 141 | | Config | Value | 142 | |--------------------- | ------------------------------------------------- | 143 | | **Grant Type** | Resource Owner Password Credentials | 144 | | **Username** | Admin user name | 145 | | **Password** | Admin user password | 146 | | **Access Token URL** | `https://replace-with-your-host/api/oauth/token` | 147 | | **Client ID** | `administration` | 148 | -------------------------------------------------------------------------------- /docs/guides/quick-start/03-media-handling.md: -------------------------------------------------------------------------------- 1 | --- 2 | stoplight-id: c042ae0cd330f 3 | --- 4 | 5 | # Media Management 6 | 7 | A common task when performing product imports is the upload/creation of product images. 8 | 9 | In Shopware, this is handled in a two-step process, which allows for the separation between writing the associations between media objects and uploading the actual data. 10 | 11 | 1. Create a media entity associated with a product entity 12 | 2. Attach resource data to the media object 13 | 1. Either reference an image resource via URL or 14 | 2. Upload the resource directly 15 | 16 | In the following, we will go through these steps in more detail. Before proceeding, ensure you have gone through the section on writing [Product Data](02-product-management.md). 17 | 18 | ## 1. Create a media entity associated with a product entity 19 | 20 | The product media model is entirely relational and based on three elementary entities: 21 | 22 | * product 23 | * media 24 | * product_media 25 | 26 | The `product` and `media` entities are connected by the `product_media` relation and have the following structure: 27 | 28 | **Product** 29 | 30 | ```json json_schema 31 | { 32 | "type": "object", 33 | "description": "Product: Subset of the product object (not the entire object)", 34 | "properties": { 35 | "id": { 36 | "type": "string", 37 | "description": "Identifier of the Product object" 38 | }, 39 | "media": { 40 | "type": "array", 41 | "description": "All ProductMedia items related to the product", 42 | "items": { 43 | "type": "ProductMedia" 44 | } 45 | }, 46 | "cover": { 47 | "type": "object", 48 | "description": "Single ProductMedia item used as product cover" 49 | }, 50 | "coverId": { 51 | "type": "string", 52 | "description": "Identifier of a ProductMedia item used as product cover" 53 | } 54 | } 55 | } 56 | ``` 57 | 58 | **Media** 59 | 60 | ```json json_schema 61 | { 62 | "type": "object", 63 | "description": "Media: Subset of the media object (not the entire object)", 64 | "properties": { 65 | "id": { 66 | "type": "string", 67 | "description": "Identifier of the Media object" 68 | } 69 | } 70 | } 71 | ``` 72 | 73 | **ProductMedia** 74 | 75 | ```json json_schema 76 | { 77 | "type": "object", 78 | "description": "ProductMedia: Object relating product and media entities", 79 | "properties": { 80 | "id": { 81 | "type": "string", 82 | "description": "Identifier of the ProductMedia object." 83 | }, 84 | "productId": { 85 | "type": "string", 86 | "description": "Identifier of the related Product object." 87 | }, 88 | "mediaId": { 89 | "type": "string", 90 | "description": "Identifier of the related Media object." 91 | }, 92 | "position": { 93 | "type": "integer", 94 | "description": "Position of the displayed item in the list of product images" 95 | } 96 | } 97 | } 98 | ``` 99 | 100 | Based on the guide on writing [Associations](../../concepts/endpoint-structure/writing-entities/associations.md), you will already know how to handle nested associations, e.g., write media and product_media using the product endpoint. Hence, we are showing the most straightforward way of creating media entities and associating them with a product: 101 | 102 | **Try it out** 103 | 104 | ```sample http 105 | { 106 | "method": "patch", 107 | "url": "http://localhost/api/product/a55ca50a2cef46d5b11a12c4b4614988", 108 | "headers": { 109 | "Content-Type": "application/json", 110 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 111 | }, 112 | "body": { 113 | "media": [{ 114 | "id": "0fa91ce3e96a4bc2be4bd9ce752c3425", 115 | "media": { 116 | "id": "cfbd5018d38d41d8adca10d94fc8bdf0" 117 | } 118 | }] 119 | } 120 | } 121 | ``` 122 | 123 | ```json 124 | // PATCH /api/product/a55ca50a2cef46d5b11a12c4b4614988 125 | 126 | { 127 | "media": [{ 128 | "id": "0fa91ce3e96a4bc2be4bd9ce752c3425", 129 | "media": { 130 | "id": "cfbd5018d38d41d8adca10d94fc8bdf0" 131 | } 132 | }] 133 | } 134 | ``` 135 | 136 | This request updates a given product and creates an array of media items. Make sure you keep track of the IDs you have created because you will need them for the second step. 137 | 138 | > A good idea is to generate `product_media` and `media` IDs based on a product identifier in combination with another property, like its position in the product image list and hashing it. This way, you don't have to perform any additional lookups. 139 | 140 | Now that you have an idea of the structure of media items, we can start uploading resources. 141 | 142 | ## 2. Attach resource data to the media object 143 | 144 | This step is about attaching the actual image data. This can be done in two ways - provide a link to a resource, and Shopware will download the file from there or provide the data within the request body. We will have a look at both ways: 145 | 146 | ### Provide a resource URL 147 | 148 | This way, you provide the `mediaId` (id of the Media, not the ProductMedia) as a path parameter, the image `url` as a body parameter, and the image `extension` as a query parameter. 149 | 150 | **Try it yourself** 151 | 152 | ```sample http 153 | { 154 | "method": "post", 155 | "url": "http://localhost/api/_action/media/0fa91ce3e96a4bc2be4bd9ce752c3425/upload?extension=jpg", 156 | "headers": { 157 | "Content-Type": "application/json", 158 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 159 | }, 160 | "body": { 161 | "url": "" 162 | }, 163 | "query": { 164 | "extension": "jpg" 165 | } 166 | } 167 | ``` 168 | 169 | ### Upload the resource directly 170 | 171 | This way, you provide the binary file directly within the request body, set the content type header accordingly (e.g., `Content-Type: image/jpg`), and provide the `extension` as a query parameter. 172 | 173 | ```sample http 174 | { 175 | "method": "post", 176 | "url": "http://localhost/api/_action/media/0fa91ce3e96a4bc2be4bd9ce752c3425/upload?extension=jpg", 177 | "headers": { 178 | "Content-Type": "image/jpg", 179 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 180 | }, 181 | "body": { 182 | // binary file body 183 | }, 184 | "query": { 185 | "extension": "jpg" 186 | } 187 | } 188 | ``` 189 | -------------------------------------------------------------------------------- /docs/guides/quick-start/06-cms-handling.md: -------------------------------------------------------------------------------- 1 | --- 2 | stoplight-id: s92t5mvj387wz 3 | --- 4 | 5 | # CMS Management 6 | 7 | Shopware's built-in CMS system is referred to as "Shopping Experiences". It is built upon layouts that can be reused and dynamically hydrated based on their assignments to categories or other entities. 8 | 9 | Using CMS REST API, you can perform CRUD operations on section, slot, block, and page templates. 10 | 11 | To fetch a list of existing CMS layouts, 12 | 13 | ``` 14 | POST /api/search/cms-page 15 | ``` 16 | 17 | ## Create a layout/page 18 | 19 | ```sample http 20 | { 21 | "method": "post", 22 | "url": "https://localhost/api/cms-page", 23 | "headers": { 24 | "Content-Type": "application/json", 25 | "Accept": "application/json", 26 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 27 | }, 28 | "body": { 29 | "name": "Summer BBQ", 30 | "type": "landingpage", 31 | "sections": [ 32 | { 33 | "position": 1, 34 | "type": "default", 35 | "sizingMode": "boxed", 36 | "backgroundColor": "#c9e4e6ff", 37 | "pageId": "f565491912994bcca19657c40b646836", 38 | "blocks": [ 39 | { 40 | "position": 0, 41 | "type": "image-text", 42 | "sectionPosition": "main", 43 | "marginTop": "169px", 44 | "marginBottom": "169px", 45 | "marginLeft": "20px", 46 | "marginRight": "20px", 47 | "backgroundColor": "#c9e4e6ff", 48 | "sectionId": "034982027a3f41f99981ba6886dc38f4", 49 | "slots": [ 50 | { 51 | "type": "text", 52 | "slot": "right", 53 | "config": { 54 | "content": { 55 | "value": "S U M M E R   T R E N D S

Be prepared for the best?
party this summer

Summer is finally here and lures us outside with its warm rays of sunshine. The heat is better tolerated with cool snacks, drinks and fresh treats.

", 56 | "source": "static" 57 | } 58 | }, 59 | "blockId": "99a324f2f2dd4f76a36700bae20977f5" 60 | } 61 | ] 62 | } 63 | ] 64 | } 65 | ] 66 | } 67 | } 68 | } 69 | ``` 70 | 71 | ```section_description json_schema 72 | { 73 | "type": "object", 74 | "description": "Parameters for CMS page.", 75 | "properties": { 76 | "sizingMode": { 77 | "description": "Accepts two values `boxed` and `full-width`. ", 78 | "type": "string" 79 | }, 80 | "backgroundColor": { 81 | "description": "Hex code of a color to be used as background.", 82 | "type": "string" 83 | }, 84 | "pageId": { 85 | "description": "Unique ID of page.", 86 | "type": "string" 87 | }, 88 | "position": { 89 | "description": "The order in which sections are to be represented when many instances of each are defined.", 90 | "type": "integer" 91 | }, 92 | "type": { 93 | "description": "Default type.", 94 | "type": "string" 95 | } 96 | } 97 | } 98 | ``` 99 | 100 | ```block_description json_schema 101 | { 102 | "type": "object", 103 | "description": "Parameters for CMS block.", 104 | "properties": { 105 | "position": { 106 | "description": "The order in which sections are to be represented when many instances of each are defined.", 107 | "type": "string" 108 | }, 109 | "backgroundColor": { 110 | "description": "Hex code of a color to be used as background.", 111 | "type": "string" 112 | }, 113 | "pageId": { 114 | "description": "Unique ID of page.", 115 | "type": "string" 116 | }, 117 | "sectionPosition": { 118 | "description": "Accepts `main` and `side-bar` values.", 119 | "type": "integer" 120 | }, 121 | "type": { 122 | "description": "Accepts `product-listing` and `sidebar-filter` values. ", 123 | "type": "string" 124 | }, 125 | "marginTop": { 126 | "description": "Size of the bottom margin of a block defined. ", 127 | "type": "string" 128 | }, 129 | "marginBottom": { 130 | "description": "Size of the bottom margin of a block defined.", 131 | "type": "string" 132 | }, 133 | "marginRight": { 134 | "description": "Size of the right margin of a block defined. ", 135 | "type": "string" 136 | }, 137 | "marginLeft": { 138 | "description": "Size of the left margin of a block defined. ", 139 | "type": "string" 140 | } 141 | } 142 | } 143 | ``` 144 | 145 | ```slot_description json_schema 146 | { 147 | "type": "object", 148 | "description": "Parameters for CMS page.", 149 | "properties": { 150 | "type": { 151 | "description": "Accepts `image-text`, `text`, `image`, `form`, `video`, `commerce`, `category-navigation`.", 152 | "type": "string" 153 | }, 154 | "slot": { 155 | "description": "The position of slot `right`, `left`.", 156 | "type": "string" 157 | }, 158 | "config": { 159 | "description": "Allows to add any customized information with styling.", 160 | "type": "string" 161 | }, 162 | "blockId": { 163 | "description": "Unique ID of the block.", 164 | "type": "integer" 165 | } 166 | } 167 | } 168 | ``` 169 | 170 | ## Create a category with layout/page 171 | 172 | Now that we have defined a layout, you can use it to create a category. Let us here assign the "Summer BBQ" layout to our new "Summer Collection" category. 173 | 174 | The UUID of the layout/page will be placed in the url. 175 | 176 | ```sample http 177 | { 178 | "method": "post", 179 | "url": "http://localhost/api/cms-page/1017542d756d4c87a9df5a35a8e18f84/categories", 180 | "headers": { 181 | "Content-Type": "application/json", 182 | "Accept": "application/json", 183 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 184 | }, 185 | "body": { 186 | "parentId": "bda4b60e845240b2b9d6b60e71196e14", 187 | "afterCategoryId": "ca15f1e906204da49afe666bbcca7825", 188 | "displayNestedProducts": true, 189 | "type": "page", 190 | "productAssignmentType": "product", 191 | "active": true, 192 | "name": "Summer Collection" 193 | } 194 | } 195 | ``` 196 | 197 | ```description json_schema 198 | { 199 | "type": "object", 200 | "description": "Parameters for assigning cms layout to category.", 201 | "properties": { 202 | "parentId": { 203 | "description": "The parentId is the UUID of the parent category tree (for example \"Collections\").", 204 | "type": "string" 205 | }, 206 | "afterCategoryId": { 207 | "description": "Unique identity of a category after which the specific category needs to be added (for example after \"Spring Collection\").", 208 | "type": "string" 209 | }, 210 | "displayNestedProducts": { 211 | "description": "When set to true, it shows all the products.", 212 | "type": "string" 213 | }, 214 | "type": { 215 | "description": "Accepts `page`, `folder` and `link` type of categories.", 216 | "type": "string" 217 | }, 218 | "productAssignmentType": { 219 | "description": "Takes values `product` and `product-stream`. ", 220 | "type": "string" 221 | }, 222 | "active": { 223 | "description": "The active category is shown and used in the frontend. If switched to inactive, it's not in use and won't be shown in the frontend.", 224 | "type": "boolean" 225 | }, 226 | "name": { 227 | "description": "Name of the category.", 228 | "type": "string" 229 | } 230 | } 231 | } 232 | ``` 233 | -------------------------------------------------------------------------------- /docs/concepts/endpoint-structure/request-response-structure.md: -------------------------------------------------------------------------------- 1 | # Request & Response Structure 2 | 3 | The Admin API provides a base endpoint to which all other endpoints are relative. 4 | 5 | The base endpoint depends on your Shopware host URL - for example: 6 | 7 | ```text 8 | https://shop.example.com/api 9 | ``` 10 | 11 | From this base endpoint, we can assemble almost all paths described in the subsequent sections. 12 | 13 | ## Request format 14 | 15 | The request format for the Shopware 6 Admin API must follow the below format: 16 | 17 | * The request body has to be JSON encoded. 18 | 19 | * It is mandatory to use type-safe values, e.g., if the API expects an integer value, you are required to provide an actual integer. 20 | 21 | * When using a Date field, make sure to use an ISO 8601 compatible date format. 22 | 23 | ### Request URL 24 | 25 | The Admin API can be separated into two general sets of endpoints 26 | 27 | * Generic entity endpoints 28 | 29 | * Specific interaction/configuration endpoints 30 | 31 | Both fulfill specific cases which are outlined below. 32 | 33 | #### Generic entity endpoints 34 | 35 | Provide CRUD functionalities on **all entities available** in Shopware. Go to the [Entity Reference](../../resources/entity-reference.md) section to see a list of all available entities and their structure. 36 | 37 | Furthermore, these endpoints can be divided into **read** and **write** operations. To learn more about those, please head to the corresponding guide on [Reading Entities](reading-entities.md) and [Writing Entities](writing-entities/README.md). These endpoints are generic, since they are entirely based on the entity definitions and contain no additional business logic besides data validation. 38 | 39 | > The URL structure for *Generic entity endpoints* is: 40 | > ``` 41 | > /api/{entity-name}(/{entity-id}) 42 | > ``` 43 | 44 | #### Specific interaction or configuration endpoints 45 | 46 | Provide interactions for more sophisticated operations that can change the system's state but are not directly based on entities alone. We differ between more than 20 categories of about 140 specific endpoints, such as: 47 | 48 | * Document Management 49 | * Order State Management 50 | * User Role Management 51 | * System Operations 52 | * Authorization & Authentication 53 | 54 | which will let you automate every part of the store operation. 55 | 56 | > The URL structure for *Specific interaction or configuration endpoints* roughly follows this schema: 57 | > ``` 58 | > /api/_action/{interaction-name} 59 | > ``` 60 | 61 | ### Request headers 62 | 63 | Request headers provide information about your request to a REST API service that allows you to authenticate/authorize and receive the request body. 64 | 65 | | Request header | Key | Description | 66 | | --------------------------- | ---------------------------------------|--------------------------------------------------------------------------------------------| 67 | | Content-Type | application/json or application/vnd.api+json | Indicate the format of the request body | 68 | | Accept | application/json | Indicate the format in which the response will be returned | 69 | 70 | Refer to the docs for more information on other [response headers](https://developer.shopware.com/docs/guides/integrations-api/general-concepts/request-headers.html#request-headers). 71 | 72 | ### Request body 73 | 74 | ```json 75 | { 76 | "id": "01bd7e70a50443ec96a01fd34890dcc5", 77 | "name": "Example product", 78 | "taxId": "792203a53e564e28bcb7ffa1867fb485", 79 | "stock": 708, 80 | "createdAt": "2018-09-13T10:17:05+02:00" 81 | } 82 | ``` 83 | 84 | ## Response format 85 | 86 | ### Response headers 87 | 88 | The Admin API generally supports two response body formats. A simple json format to no explicit specification and the [JSON:API](http://jsonapi.org/) standard format. By default, the response will be in JSON:API format. You can control the response format using the `Accept` header. 89 | 90 | | Accept | Format | 91 | | --------------------------- | ----------------------------------------- | 92 | | `application/vnd.api+json` | JSON:API formatted response **(default)** | 93 | | `application/json` | Simplified JSON format | 94 | 95 | ### Sample response JSON:API 96 | 97 | The format has a rich structure that makes discovering the API easier, even without documentation. Some libraries can even generate user interfaces from it. It provides relationships to other resources and additional information about the resource. You can see a shortened example response below 98 | 99 | ```javascript 100 | // Accept: application/vnd.api+json (default) 101 | 102 | { 103 | "data": [ 104 | { 105 | "id": "01bd7e70a50443ec96a01fd34890dcc5", 106 | "type": "product", 107 | "attributes": { 108 | "active": true, 109 | "stock": 708, 110 | "createdAt": "2018-09-13T10:17:05+02:00", 111 | "manufacturerId": "f85bda8491fd4d61bcd2c7982204c638", 112 | "taxId": "792203a53e564e28bcb7ffa1867fb485", 113 | "price": { 114 | "net": 252.94117647058826, 115 | "gross": 301, 116 | "linked": true 117 | } 118 | }, 119 | "links": { 120 | "self": "http://localhost:8000/api/product/01bd7e70a50443ec96a01fd34890dcc5" 121 | }, 122 | "relationships": { 123 | "children": { 124 | "data": [], 125 | "links": { 126 | "related": "http://localhost:8000/api/product/01bd7e70a50443ec96a01fd34890dcc5/children" 127 | } 128 | } 129 | } 130 | } 131 | ], 132 | "included": [ 133 | { 134 | "id": "792203a53e564e28bcb7ffa1867fb485", 135 | "type": "tax", 136 | "attributes": { 137 | "taxRate": 20, 138 | "name": "20%", 139 | "createdAt": "2018-09-13T09:54:01+02:00" 140 | }, 141 | "links": { 142 | "self": "http://localhost:8000/api/tax/792203a53e564e28bcb7ffa1867fb485" 143 | }, 144 | "relationships": { 145 | "products": { 146 | "data": [], 147 | "links": { 148 | "related": "http://localhost:8000/api/tax/792203a53e564e28bcb7ffa1867fb485/products" 149 | } 150 | } 151 | } 152 | } 153 | ], 154 | "links": { 155 | "first": "http://localhost:8000/api/product?limit=1&page=1", 156 | "last": "http://localhost:8000/api/product?limit=1&page=50", 157 | "next": "http://localhost:8000/api/product?limit=1&page=2", 158 | "self": "http://localhost:8000/api/product?limit=1" 159 | }, 160 | "meta": { 161 | "fetchCount": 1, 162 | "total": 50 163 | }, 164 | "aggregations": [] 165 | } 166 | ``` 167 | 168 | ### Sample response JSON 169 | 170 | The simple JSON format only contains essential information, and skips JSON:API specific fields related to pagination or self-discovery. Associations are placed directly within the entities rather than in a separate section. It is sometimes favourable, because it's less "blown-up" and as such easier for clients to consume. You can see a shortened example below: 171 | 172 | ```javascript 173 | // Accept: application/json 174 | 175 | { 176 | "total": 50, 177 | "data": [ 178 | { 179 | "taxId": "792203a53e564e28bcb7ffa1867fb485", 180 | "manufacturerId": "f85bda8491fd4d61bcd2c7982204c638", 181 | "active": true, 182 | "price": { 183 | "net": 252.94117647058826, 184 | "gross": 301, 185 | "linked": true, 186 | "extensions": [] 187 | }, 188 | "stock": 708, 189 | "tax": { 190 | "taxRate": 20, 191 | "name": "20%", 192 | "createdAt": "2018-09-13T09:54:01+02:00", 193 | "id": "792203a53e564e28bcb7ffa1867fb485" 194 | }, 195 | "manufacturer": { 196 | "catalogId": "20080911ffff4fffafffffff19830531", 197 | "name": "Arnold", 198 | "createdAt": "2018-09-13T10:17:04+02:00", 199 | "products": null, 200 | "id": "f85bda8491fd4d61bcd2c7982204c638" 201 | }, 202 | "parent": null, 203 | "children": null, 204 | "id": "01bd7e70a50443ec96a01fd34890dcc5" 205 | } 206 | ], 207 | "aggregations": [] 208 | } 209 | ``` 210 | -------------------------------------------------------------------------------- /docs/concepts/endpoint-structure/writing-entities/README.md: -------------------------------------------------------------------------------- 1 | # Writing entities 2 | 3 | Analogous to the reading endpoints, the API also provides endpoints for all entities to be written in the same way. Once an entity is registered in the system, it can also be written via API. The appropriate routes for the entity are generated automatically and follow the REST pattern. 4 | 5 | A list of all entities available for these operations can be found in the [Entity Reference](../../../resources/entity-reference.md). 6 | 7 | **Example:** The entity `customer_group` is available under the endpoint `api/customer-group`. For an entity, the system automatically generates the following routes where the entity can be written 8 | 9 | | Name | Method | Route | Usage | 10 | | :--- | :--- | :--- | :--- | 11 | | api.customer\_group.update | PATCH | /api/customer-group/{id} | Update the entity with the provided ID | 12 | | api.customer\_group.delete | DELETE | /api/customer-group/{id} | Delete the entity | 13 | | api.customer\_group.create | POST | /api/customer-group | Create a new entity | 14 | 15 | 16 | > **PATCH** method only adds properties and does not delete old references. To perform both operations, use [Sync API](bulk-payloads.md) endpoints. 17 | 18 | ## Payload 19 | 20 | The payload for writing entities is dictated by the API scheme, which in turn is generated from entity definitions which are part of the Shopware core \(unless they are custom entities\). 21 | 22 | See the [Entity Reference](../../../resources/entity-reference.md) section of this documentation to inspect the scheme of all entities. 23 | 24 | > If it is not clear how the data has to be sent despite the scheme, it is also possible to open the administration and to have a look at the corresponding requests. To do this, simply open the network tab in the developer tools of your browser, which lists all requests and payloads sent by the administration. 25 | 26 | ### Primary Keys 27 | 28 | Shopware 6 works with UUIDv4 as primary keys instead of auto increments. We have opted for this standard for the following reasons: 29 | 30 | * IDs can be provided \(client-generated\) when creating an entity 31 | * Minuscule likelihood of generating ID collisions 32 | * Data integrations become easier, because existing primary keys can be hashed to generate UUIDs 33 | 34 | > Shopware doesn't check UUIDs for validity, so if you're creating an import, you can hash a primary key of your record and use it as its Shopware id. 35 | > ```php 36 | > $payload[] = [ 37 | > 'id' => md5($product->getUniqueIdentifier()); 38 | > ] 39 | > ``` 40 | > This way, you can later on use that identifier to push instant updates to the changed records. Of course, you can use a similar pattern for related entities. 41 | 42 | ### **Bulk Payloads** 43 | 44 | If you intend to write multiple entities of a different type or perform various operations \(update, delete\) within a single request, take a look at the [sync endpoint or Sync API](bulk-payloads.md). 45 | 46 | ## Creating entities 47 | 48 | When creating an entity, all `required` fields must be provided in the request body. If one or more fields have not been passed or contain incorrect data, the API outputs all errors for an entity: 49 | 50 | ```sample http 51 | { 52 | "method": "POST", 53 | "url": "http://localhost/api/product", 54 | "headers": { 55 | "Content-Type": "application/json", 56 | "Accept": "application/json", 57 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 58 | }, 59 | "body": { 60 | "name" : "test" 61 | } 62 | } 63 | ``` 64 | 65 | ### Response 66 | 67 | ```javascript 68 | { 69 | "errors": [ 70 | { 71 | "code": "c1051bb4-d103-4f74-8988-acbcafc7fdc3", 72 | "status": "400", 73 | "detail": "This value should not be blank.", 74 | "source": { 75 | "pointer": "/0/taxId" 76 | } 77 | }, 78 | { 79 | "code": "c1051bb4-d103-4f74-8988-acbcafc7fdc3", 80 | "status": "400", 81 | "detail": "This value should not be blank.", 82 | "source": { 83 | "pointer": "/0/stock" 84 | } 85 | }, 86 | { 87 | "code": "c1051bb4-d103-4f74-8988-acbcafc7fdc3", 88 | "status": "400", 89 | "detail": "This value should not be blank.", 90 | "source": { 91 | "pointer": "/0/price" 92 | } 93 | }, 94 | { 95 | "code": "c1051bb4-d103-4f74-8988-acbcafc7fdc3", 96 | "status": "400", 97 | "detail": "This value should not be blank.", 98 | "source": { 99 | "pointer": "/0/productNumber" 100 | } 101 | } 102 | ] 103 | } 104 | ``` 105 | 106 | If the entity has been successfully created, the API responds with a `204 No Content` status code. 107 | ```sample http 108 | { 109 | "method": "POST", 110 | "url": "http://localhost/api/product", 111 | "headers": { 112 | "Content-Type": "application/json", 113 | "Accept": "application/json", 114 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 115 | }, 116 | "body": { 117 | "name" : "test", 118 | "productNumber" : "random", 119 | "stock" : 10, 120 | "price" : [ 121 | { 122 | "currencyId" : "b7d2554b0ce847cd82f3ac9bd1c0dfca", 123 | "gross": 15, 124 | "net": 10, 125 | "linked" : false 126 | } 127 | ], 128 | "tax" : { 129 | "name": "test", 130 | "taxRate": 15 131 | } 132 | } 133 | } 134 | ``` 135 | 136 | ## Updating entities 137 | 138 | Updating an entity can, and should, be done partially. This means that only the fields to be updated should be sent in the request. This is recommended because the system reacts differently in the background to certain field changes. 139 | 140 | For example, to update the stock of a product and update the price at the same time, we recommend the following partial payload: 141 | 142 | ```sample http 143 | { 144 | "method": "PATCH", 145 | "url": "http://localhost/api/product/021523dde52d42c9a0b005c22ac85043", 146 | "headers": { 147 | "Content-Type": "application/json", 148 | "Accept": "application/json", 149 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 150 | }, 151 | "body": { 152 | "stock": 10, 153 | "price": [ 154 | { 155 | "currencyId": "b7d2554b0ce847cd82f3ac9bd1c0dfca", 156 | "gross": 99.99, 157 | "net": 89.99, 158 | "linked": false 159 | } 160 | ] 161 | } 162 | } 163 | ``` 164 | 165 | ## Deleting entities 166 | 167 | To delete an entity the route `DELETE /api/product/{id}` can be used. If the entity has been successfully deleted, the API returns a `204 - No Content` response. 168 | 169 | When deleting data, it can happen that this is prevented by foreign key restrictions. This happens if the entity is still linked to another entity which requires the relation. For example, if you try to delete a tax record which is marked as required for a product, the delete request will be prevented with a `409 - Conflict.` Make sure to resolve these cascading conflicts before deleting a referenced entity. 170 | 171 | ```sample http 172 | { 173 | "method": "DELETE", 174 | "url": "http://localhost/api/tax/5840ff0975ac428ebf7838359e47737f", 175 | "headers": { 176 | "Content-Type": "application/json", 177 | "Accept": "application/json", 178 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 179 | } 180 | } 181 | ``` 182 | ### Response 183 | 184 | ```javascript 185 | { 186 | "errors": [ 187 | { 188 | "status": "409", 189 | "code": "FRAMEWORK__DELETE_RESTRICTED", 190 | "title": "Conflict", 191 | "detail": "The delete request for tax was denied due to a conflict. The entity is currently in use by: product (32)" 192 | } 193 | ] 194 | } 195 | ``` 196 | 197 | ## Cloning an entity 198 | 199 | To clone an entity the route `POST /api/_action/clone/{entity}/{id}` can be used. The API clones all associations which are marked with `CascadeDelete`. 200 | 201 | The behaviour can be disabled explicitly by setting the constructor argument for `CascadeDelete` to false in the entity definition 202 | 203 | ```php 204 | (new OneToManyAssociationField('productReviews', /* ... */)) 205 | ->addFlags(new CascadeDelete(false)), 206 | ``` 207 | 208 | Some entities have a `ChildrenAssociationField`. The children are also considered in a clone request. However, since this results in large amounts of data, the parameter `cloneChildren: false` can be sent in the payload so that they are no longer duplicated. It is also possible to overwrite fields in the clone using the payload parameter 'overwrites'. This is especially helpful if the entity has a unique constraint in the database. As response, the API returns the new id of the entity: 209 | 210 | ```sample http 211 | { 212 | "method": "POST", 213 | "url": "http://localhost/api/_action/clone/product/53be6fb93e4b44ed877736cbe01a47b8", 214 | "headers": { 215 | "Content-Type": "application/json", 216 | "Accept": "application/json", 217 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 218 | }, 219 | "body": { 220 | "overwrites": { 221 | "name" : "New name", 222 | "productNumber" : "new number" 223 | }, 224 | "cloneChildren": false 225 | } 226 | } 227 | ``` 228 | 229 | ### Response 230 | 231 | ```javascript 232 | { 233 | "id": "cddde8ad9f81497b9a280c7eb5c6bd2e" 234 | } 235 | ``` 236 | -------------------------------------------------------------------------------- /docs/concepts/endpoint-structure/writing-entities/bulk-payloads.md: -------------------------------------------------------------------------------- 1 | # Bulk Payloads 2 | 3 | The Sync API is an add-on to the Admin API that allows you to perform multiple write operations \(creating/updating and deleting\) simultaneously. All entities that can be written via the Admin API can also be written via the Sync API. 4 | 5 | The endpoint is located at 6 | 7 | ```text 8 | /api/_action/sync 9 | ``` 10 | 11 | and expects payloads via `POST` and `Content-Type: application/json`. 12 | 13 | ## Operations 14 | 15 | In contrast to the Admin API, the Sync API does not differ between **create** and **update** operations, but always performs an **upsert** operation. During an **upsert**, the system checks whether the entity already exists in the system and updates it if an ID has been passed, otherwise a new entity is created with this ID. 16 | 17 | A request always contains a **list of operations**. An operation defines the `action` to be executed \(`upsert` or `delete`\), an associated `entity` and the `payload` which is an array of multiple records \(for `upsert`\) or multiple IDs \(for `delete`\). Within a request, different entities can therefore be written in batch. For easier debugging, each operation can be given a key. The key is then used in the response to define which entities are written in which operation. 18 | 19 | **Format of an operation** 20 | 21 | | Field | Values | 22 | | :--- | :--- | 23 | | **entity** | Any entity in Shopware, e.g. `category`or `customer` | 24 | | **action** | The type of operation - either `upsert` or `delete` | 25 | | **payload** | A list containing objects or a list of IDs | 26 | 27 | ### Writing entities 28 | 29 | Writing entities is performed with `upsert` operation. This operation is used to insert or update an array of multiple records with their data. The records in the payload for a bulk upsert operation typically represent individual entities (such as products, customers, or orders) with their corresponding data. The specific fields and data within each record depend on the entity you are working with. Here are examples for three different entities: tax, category and country. 30 | 31 | ```sample http 32 | { 33 | "method": "POST", 34 | "url": "http://localhost/api/_action/sync", 35 | "headers": { 36 | "Content-Type": "application/json", 37 | "Accept": "application/json", 38 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 39 | }, 40 | "body": { 41 | "write-tax": { 42 | "entity": "tax", 43 | "action": "upsert", 44 | "payload": [ 45 | { "name": "tax-1", "taxRate": 16 }, 46 | { "name": "tax-2", "taxRate": 15 } 47 | ] 48 | }, 49 | "write-category": { 50 | "entity": "category", 51 | "action": "upsert", 52 | "payload": [ 53 | { "name": "category-1" }, 54 | { "name": "category-2" } 55 | ] 56 | }, 57 | "write-country": { 58 | "entity": "country", 59 | "action": "upsert", 60 | "payload": [ 61 | { "name": "country-1" }, 62 | { "name": "country-2" } 63 | ] 64 | } 65 | } 66 | } 67 | ``` 68 | 69 | #### Response 70 | 71 | ```javascript 72 | { 73 | "extensions": [], 74 | "data": { 75 | "category": [ 76 | "0189bf2a627a7296adbc83527ba9ac29", 77 | "0189bf2a627b719999a9bf3afdc5c5ac" 78 | ], 79 | "category_translation": [ 80 | { 81 | "categoryId": "0189bf2a627a7296adbc83527ba9ac29", 82 | "languageId": "2fbb5fe2e29a4d70aa5854ce7ce3e20b" 83 | }, 84 | { 85 | "categoryId": "0189bf2a627b719999a9bf3afdc5c5ac", 86 | "languageId": "2fbb5fe2e29a4d70aa5854ce7ce3e20b" 87 | } 88 | ], 89 | "country": [ 90 | "0189bf2a627e723dbf691bd638113c02", 91 | "0189bf2a627e723dbf691bd638ca0a34" 92 | ], 93 | "country_translation": [ 94 | { 95 | "countryId": "0189bf2a627e723dbf691bd638113c02", 96 | "languageId": "2fbb5fe2e29a4d70aa5854ce7ce3e20b" 97 | }, 98 | { 99 | "countryId": "0189bf2a627e723dbf691bd638ca0a34", 100 | "languageId": "2fbb5fe2e29a4d70aa5854ce7ce3e20b" 101 | } 102 | ], 103 | "tax": [ 104 | "0189bf2a627971fcb6de1311115ee7fe", 105 | "0189bf2a627971fcb6de131111ad13cd" 106 | ] 107 | }, 108 | "notFound": [], 109 | "deleted": [] 110 | } 111 | ``` 112 | 113 | ### Deleting entities 114 | 115 | To delete entities, the `payload` of an operation contains the IDs. If the entity is a `MappingEntityDefinition` \(e.g. `product_category`\) the foreign keys, which are the primary keys of the corresponding entities, must be passed. 116 | 117 | ```sample http 118 | { 119 | "method": "POST", 120 | "url": "http://localhost/api/_action/sync", 121 | "headers": { 122 | "Content-Type": "application/json", 123 | "Accept": "application/json", 124 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 125 | }, 126 | "body": { 127 | "delete-tax": { 128 | "entity": "category", 129 | "action": "delete", 130 | "payload": [ 131 | { "id": "1d0943f296a94b06b785dfb4b017c18b" }, 132 | { "id": "046e9574bdae4478b854f49a8f22c275" }, 133 | { "id": "0a5bff83cbdf45968d37d30c31beac69" } 134 | ] 135 | }, 136 | "delete-product-category": { 137 | "entity": "product_category", 138 | "action": "delete", 139 | "payload": [ 140 | { 141 | "productId": "000bba26e2044b98a3ee4a84b03f9551", 142 | "categoryId": "0446a1eb394c4e729178699a7bc2833f" 143 | }, 144 | { 145 | "productId": "5deed0c33b2a4866a6b2c88fa215561c", 146 | "categoryId": "0446a1eb394c4e729178699a7bc2833f" 147 | } 148 | ] 149 | } 150 | } 151 | } 152 | ``` 153 | 154 | ### Deleting Relations 155 | 156 | You can't delete relations by updating the owning entity. Instead you have to delete the relation on the relation entity `MappingEntityDefinition` \(e.g. `product_property`\). The corresponding entries in the main entity \(here `product`\) will be updated with an [indexer](#performance) that will immediately run after the delete. 157 | 158 | ```sample http 159 | { 160 | "method": "POST", 161 | "url": "http://localhost/api/_action/sync", 162 | "headers": { 163 | "Content-Type": "application/json", 164 | "Accept": "application/json", 165 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 166 | }, 167 | "body": { 168 | "delete-product-property": { 169 | "entity": "product_property", 170 | "action": "delete", 171 | "payload": [ 172 | { "productId": "000bba26e2044b98a3ee4a84b03f9551", "optionId": "0446a1eb394c4e729178699a7bc2833f" }, 173 | { "productId": "5deed0c33b2a4866a6b2c88fa215561c", "optionId": "0446a1eb394c4e729178699a7bc2833f" } 174 | ] 175 | } 176 | } 177 | } 178 | ``` 179 | 180 | ### Deleting mapping entities via criteria 181 | 182 | When you want to clear a many-to-many association of an entity, or want to delete multiple mappings in a single request without passing all combined foreign keys, you can also use a criteria syntax in the sync operation. 183 | 184 | ```sample http 185 | [ 186 | { 187 | "action": "delete", 188 | "entity": "product_category", 189 | "criteria": [ 190 | {"type": "equals", "field": "productId", "value": "2fbb5fe2e29a4d70aa5854ce7ce3e20b"} 191 | ] 192 | } 193 | ] 194 | ``` 195 | 196 | The api resolves the criteria for the mapping entity and uses the detected primary keys for the delete operation. The criteria parameter is not combinable with the payload parameter in a single operation. 197 | 198 | You can also use a `equalsAny` to enforce that only the exact match for a value of the given list of categories is deleted. 199 | 200 | ```sample http 201 | [ 202 | { 203 | "action": "delete", 204 | "entity": "product_category", 205 | "criteria": [ 206 | {"type": "equalsAny", "field": "categoryId", "value": "2fbb5fe2e29a4d70aa5854ce7ce3e20b", "2fbb5fe2e29a4d70aa5854ce7ce3e20c", "2fbb5fe2e29a4d81aa5854ce7ce3e50c"} 207 | ] 208 | } 209 | ] 210 | ``` 211 | 212 | For more operations you can take a look at the [filter references](https://developer.shopware.com/docs/resources/references/core-reference/dal-reference/filters-reference.html) 213 | 214 | ## Performance 215 | 216 | Various indexing processes are triggered in the background, depending on which data was written. 217 | 218 | This leads to a high load on the server and can be a problem with large imports. Therefore, it is possible that the indexing is moved to an asynchronous process in the background. 219 | 220 | You can control the behaviour using the following headers: 221 | 222 | | Header | Value | Description | 223 | | :--- | :--- | :--- | 224 | | indexing-behavior | `null (default)` | Data will be indexed synchronously | 225 | | | `use-queue-indexing` | Data will be indexed asynchronously | 226 | | | `disable-indexing` | Data indexing is completely disabled | 227 | 228 | ```sample http 229 | { 230 | "method": "POST", 231 | "url": "http://localhost/api/_action/sync", 232 | "headers": { 233 | "Content-Type": "application/json", 234 | "Accept": "application/json", 235 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 236 | }, 237 | "body": { 238 | "write-tax": { 239 | "entity": "tax", 240 | "action": "upsert", 241 | "payload": [ 242 | { "name": "tax-1", "taxRate": 16 }, 243 | { "name": "tax-2", "taxRate": 15 } 244 | ] 245 | }, 246 | "write-category": { 247 | "entity": "category", 248 | "action": "upsert", 249 | "payload": [ 250 | { "name": "category-1" }, 251 | { "name": "category-2" } 252 | ] 253 | }, 254 | "write-country": { 255 | "entity": "country", 256 | "action": "upsert", 257 | "payload": [ 258 | { "name": "country-1" }, 259 | { "name": "country-2" } 260 | ] 261 | } 262 | } 263 | } 264 | ``` 265 | 266 | ## Flows 267 | 268 | To stop flows from being triggered use the `sw-skip-trigger-flow` header. See also [Request Headers](https://developer.shopware.com/docs/guides/integrations-api/general-concepts/request-headers.html#sw-skip-trigger-flow) 269 | 270 | ```sample http 271 | { 272 | "method": "POST", 273 | "url": "http://localhost/api/_action/sync", 274 | "headers": { 275 | "Content-Type": "application/json", 276 | "Accept": "application/json", 277 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 278 | "sw-skip-trigger-flow": 1 279 | }, 280 | "body": { 281 | "write-customer": { 282 | "entity": "customer", 283 | "action": "upsert", 284 | "payload": [ 285 | { } 286 | ] 287 | } 288 | } 289 | } 290 | ``` 291 | 292 | 293 | ## Examples 294 | 295 | ### Update product stocks 296 | 297 | ```sample http 298 | { 299 | "method": "POST", 300 | "url": "http://localhost/api/_action/sync", 301 | "headers": { 302 | "Content-Type": "application/json", 303 | "Accept": "application/json", 304 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 305 | }, 306 | "body": { 307 | "stock-updates": { // Name of the transaction, choose freely 308 | "entity": "product", // Name of the entity you would like to update 309 | "action": "upsert", // Available actions are upsert and delete, 310 | "payload": [ // A list of objects, each representing a subset of the entity scheme referenced in `entity`. `id` is required for upsert operations. 311 | { 312 | "id": "", 313 | "stock": 42 314 | }, 315 | { 316 | "id": "", 317 | "stock": 42 318 | }, 319 | { 320 | "id": "", 321 | "stock": 42 322 | } 323 | ] 324 | } 325 | } 326 | } 327 | ``` 328 | -------------------------------------------------------------------------------- /SwagCustomizedProducts-adminapi.summary.json: -------------------------------------------------------------------------------- 1 | { 2 | "paths": [ 3 | "/search/swag-customized-products-template", 4 | "/search/swag-customized-products-template-configuration", 5 | "/search/swag-customized-products-template-configuration-share", 6 | "/search/swag-customized-products-template-exclusion", 7 | "/search/swag-customized-products-template-exclusion-condition", 8 | "/search/swag-customized-products-template-exclusion-operator", 9 | "/search/swag-customized-products-template-option", 10 | "/search/swag-customized-products-template-option-price", 11 | "/search/swag-customized-products-template-option-value", 12 | "/search/swag-customized-products-template-option-value-price", 13 | "/swag-customized-products-template", 14 | "/swag-customized-products-template-configuration", 15 | "/swag-customized-products-template-configuration-share", 16 | "/swag-customized-products-template-configuration-share/{id}", 17 | "/swag-customized-products-template-configuration/{id}", 18 | "/swag-customized-products-template-exclusion", 19 | "/swag-customized-products-template-exclusion-condition", 20 | "/swag-customized-products-template-exclusion-condition/{id}", 21 | "/swag-customized-products-template-exclusion-operator", 22 | "/swag-customized-products-template-exclusion-operator/{id}", 23 | "/swag-customized-products-template-exclusion/{id}", 24 | "/swag-customized-products-template-option", 25 | "/swag-customized-products-template-option-price", 26 | "/swag-customized-products-template-option-price/{id}", 27 | "/swag-customized-products-template-option-value", 28 | "/swag-customized-products-template-option-value-price", 29 | "/swag-customized-products-template-option-value-price/{id}", 30 | "/swag-customized-products-template-option-value/{id}", 31 | "/swag-customized-products-template-option/{id}", 32 | "/swag-customized-products-template/{id}" 33 | ], 34 | "schemas": [ 35 | "AclRole", 36 | "AclRoleJsonApi", 37 | "AclUserRole", 38 | "App", 39 | "AppActionButton", 40 | "AppActionButtonJsonApi", 41 | "AppAdministrationSnippet", 42 | "AppAdministrationSnippetJsonApi", 43 | "AppCmsBlock", 44 | "AppCmsBlockJsonApi", 45 | "AppFlowAction", 46 | "AppFlowActionJsonApi", 47 | "AppFlowEvent", 48 | "AppFlowEventJsonApi", 49 | "AppJsonApi", 50 | "AppPaymentMethod", 51 | "AppPaymentMethodJsonApi", 52 | "AppScriptCondition", 53 | "AppScriptConditionJsonApi", 54 | "AppShippingMethod", 55 | "AppShippingMethodJsonApi", 56 | "AppTemplate", 57 | "AppTemplateJsonApi", 58 | "Category", 59 | "CategoryJsonApi", 60 | "CategoryTag", 61 | "CmsBlock", 62 | "CmsBlockJsonApi", 63 | "CmsPage", 64 | "CmsPageJsonApi", 65 | "CmsSection", 66 | "CmsSectionJsonApi", 67 | "CmsSlot", 68 | "CmsSlotJsonApi", 69 | "Country", 70 | "CountryJsonApi", 71 | "CountryState", 72 | "CountryStateJsonApi", 73 | "Criteria", 74 | "Currency", 75 | "CurrencyCountryRounding", 76 | "CurrencyCountryRoundingJsonApi", 77 | "CurrencyJsonApi", 78 | "CustomEntity", 79 | "CustomEntityJsonApi", 80 | "CustomField", 81 | "CustomFieldJsonApi", 82 | "CustomFieldSet", 83 | "CustomFieldSetJsonApi", 84 | "CustomFieldSetRelation", 85 | "CustomFieldSetRelationJsonApi", 86 | "Customer", 87 | "CustomerAddress", 88 | "CustomerAddressJsonApi", 89 | "CustomerGroup", 90 | "CustomerGroupJsonApi", 91 | "CustomerGroupRegistrationSalesChannels", 92 | "CustomerJsonApi", 93 | "CustomerRecovery", 94 | "CustomerRecoveryJsonApi", 95 | "CustomerTag", 96 | "CustomerWishlist", 97 | "CustomerWishlistJsonApi", 98 | "CustomerWishlistProduct", 99 | "CustomerWishlistProductJsonApi", 100 | "DeliveryTime", 101 | "DeliveryTimeJsonApi", 102 | "Document", 103 | "DocumentBaseConfig", 104 | "DocumentBaseConfigJsonApi", 105 | "DocumentBaseConfigSalesChannel", 106 | "DocumentBaseConfigSalesChannelJsonApi", 107 | "DocumentJsonApi", 108 | "DocumentType", 109 | "DocumentTypeJsonApi", 110 | "Flow", 111 | "FlowJsonApi", 112 | "FlowSequence", 113 | "FlowSequenceJsonApi", 114 | "FlowTemplate", 115 | "FlowTemplateJsonApi", 116 | "ImportExportFile", 117 | "ImportExportFileJsonApi", 118 | "ImportExportLog", 119 | "ImportExportLogJsonApi", 120 | "ImportExportProfile", 121 | "ImportExportProfileJsonApi", 122 | "Integration", 123 | "IntegrationJsonApi", 124 | "IntegrationRole", 125 | "LandingPage", 126 | "LandingPageJsonApi", 127 | "LandingPageSalesChannel", 128 | "LandingPageTag", 129 | "Language", 130 | "LanguageJsonApi", 131 | "Locale", 132 | "LocaleJsonApi", 133 | "LogEntry", 134 | "LogEntryJsonApi", 135 | "MailHeaderFooter", 136 | "MailHeaderFooterJsonApi", 137 | "MailTemplate", 138 | "MailTemplateJsonApi", 139 | "MailTemplateMedia", 140 | "MailTemplateType", 141 | "MailTemplateTypeJsonApi", 142 | "MainCategory", 143 | "MainCategoryJsonApi", 144 | "Media", 145 | "MediaDefaultFolder", 146 | "MediaDefaultFolderJsonApi", 147 | "MediaFolder", 148 | "MediaFolderConfiguration", 149 | "MediaFolderConfigurationJsonApi", 150 | "MediaFolderConfigurationMediaThumbnailSize", 151 | "MediaFolderJsonApi", 152 | "MediaJsonApi", 153 | "MediaTag", 154 | "MediaThumbnail", 155 | "MediaThumbnailJsonApi", 156 | "MediaThumbnailSize", 157 | "MediaThumbnailSizeJsonApi", 158 | "NewsletterRecipient", 159 | "NewsletterRecipientJsonApi", 160 | "NewsletterRecipientTag", 161 | "Notification", 162 | "NotificationJsonApi", 163 | "NumberRange", 164 | "NumberRangeJsonApi", 165 | "NumberRangeSalesChannel", 166 | "NumberRangeSalesChannelJsonApi", 167 | "NumberRangeState", 168 | "NumberRangeStateJsonApi", 169 | "NumberRangeType", 170 | "NumberRangeTypeJsonApi", 171 | "OAuthClientCredentialsGrant", 172 | "OAuthGrant", 173 | "OAuthPasswordGrant", 174 | "OAuthRefreshTokenGrant", 175 | "OAuthScopes", 176 | "Order", 177 | "OrderAddress", 178 | "OrderAddressJsonApi", 179 | "OrderCustomer", 180 | "OrderCustomerJsonApi", 181 | "OrderDelivery", 182 | "OrderDeliveryJsonApi", 183 | "OrderDeliveryPosition", 184 | "OrderDeliveryPositionJsonApi", 185 | "OrderJsonApi", 186 | "OrderLineItem", 187 | "OrderLineItemDownload", 188 | "OrderLineItemDownloadJsonApi", 189 | "OrderLineItemJsonApi", 190 | "OrderTag", 191 | "OrderTransaction", 192 | "OrderTransactionCapture", 193 | "OrderTransactionCaptureJsonApi", 194 | "OrderTransactionCaptureRefund", 195 | "OrderTransactionCaptureRefundJsonApi", 196 | "OrderTransactionCaptureRefundPosition", 197 | "OrderTransactionCaptureRefundPositionJsonApi", 198 | "OrderTransactionJsonApi", 199 | "PaymentMethod", 200 | "PaymentMethodJsonApi", 201 | "Plugin", 202 | "PluginJsonApi", 203 | "Product", 204 | "ProductCategory", 205 | "ProductCategoryTree", 206 | "ProductConfiguratorSetting", 207 | "ProductConfiguratorSettingJsonApi", 208 | "ProductCrossSelling", 209 | "ProductCrossSellingAssignedProducts", 210 | "ProductCrossSellingAssignedProductsJsonApi", 211 | "ProductCrossSellingJsonApi", 212 | "ProductCustomFieldSet", 213 | "ProductDownload", 214 | "ProductDownloadJsonApi", 215 | "ProductExport", 216 | "ProductExportJsonApi", 217 | "ProductFeatureSet", 218 | "ProductFeatureSetJsonApi", 219 | "ProductJsonApi", 220 | "ProductKeywordDictionary", 221 | "ProductKeywordDictionaryJsonApi", 222 | "ProductManufacturer", 223 | "ProductManufacturerJsonApi", 224 | "ProductMedia", 225 | "ProductMediaJsonApi", 226 | "ProductOption", 227 | "ProductPrice", 228 | "ProductPriceJsonApi", 229 | "ProductProperty", 230 | "ProductReview", 231 | "ProductReviewJsonApi", 232 | "ProductSearchConfig", 233 | "ProductSearchConfigField", 234 | "ProductSearchConfigFieldJsonApi", 235 | "ProductSearchConfigJsonApi", 236 | "ProductSearchKeyword", 237 | "ProductSearchKeywordJsonApi", 238 | "ProductSorting", 239 | "ProductSortingJsonApi", 240 | "ProductStream", 241 | "ProductStreamFilter", 242 | "ProductStreamFilterJsonApi", 243 | "ProductStreamJsonApi", 244 | "ProductStreamMapping", 245 | "ProductTag", 246 | "ProductVisibility", 247 | "ProductVisibilityJsonApi", 248 | "Promotion", 249 | "PromotionCartRule", 250 | "PromotionDiscount", 251 | "PromotionDiscountJsonApi", 252 | "PromotionDiscountPrices", 253 | "PromotionDiscountPricesJsonApi", 254 | "PromotionDiscountRule", 255 | "PromotionIndividualCode", 256 | "PromotionIndividualCodeJsonApi", 257 | "PromotionJsonApi", 258 | "PromotionOrderRule", 259 | "PromotionPersonaCustomer", 260 | "PromotionPersonaRule", 261 | "PromotionSalesChannel", 262 | "PromotionSalesChannelJsonApi", 263 | "PromotionSetgroup", 264 | "PromotionSetgroupJsonApi", 265 | "PromotionSetgroupRule", 266 | "PropertyGroup", 267 | "PropertyGroupJsonApi", 268 | "PropertyGroupOption", 269 | "PropertyGroupOptionJsonApi", 270 | "Rule", 271 | "RuleCondition", 272 | "RuleConditionJsonApi", 273 | "RuleJsonApi", 274 | "RuleTag", 275 | "SalesChannel", 276 | "SalesChannelAnalytics", 277 | "SalesChannelAnalyticsJsonApi", 278 | "SalesChannelCountry", 279 | "SalesChannelCurrency", 280 | "SalesChannelDomain", 281 | "SalesChannelDomainJsonApi", 282 | "SalesChannelJsonApi", 283 | "SalesChannelLanguage", 284 | "SalesChannelPaymentMethod", 285 | "SalesChannelShippingMethod", 286 | "SalesChannelType", 287 | "SalesChannelTypeJsonApi", 288 | "Salutation", 289 | "SalutationJsonApi", 290 | "ScheduledTask", 291 | "ScheduledTaskJsonApi", 292 | "Script", 293 | "ScriptJsonApi", 294 | "SeoUrl", 295 | "SeoUrlJsonApi", 296 | "SeoUrlTemplate", 297 | "SeoUrlTemplateJsonApi", 298 | "ShippingMethod", 299 | "ShippingMethodJsonApi", 300 | "ShippingMethodPrice", 301 | "ShippingMethodPriceJsonApi", 302 | "ShippingMethodTag", 303 | "Snippet", 304 | "SnippetJsonApi", 305 | "SnippetSet", 306 | "SnippetSetJsonApi", 307 | "StateMachine", 308 | "StateMachineHistory", 309 | "StateMachineHistoryJsonApi", 310 | "StateMachineJsonApi", 311 | "StateMachineState", 312 | "StateMachineStateJsonApi", 313 | "StateMachineTransition", 314 | "StateMachineTransitionJsonApi", 315 | "SwagCustomizedProductsTemplate", 316 | "SwagCustomizedProductsTemplateConfiguration", 317 | "SwagCustomizedProductsTemplateConfigurationJsonApi", 318 | "SwagCustomizedProductsTemplateConfigurationShare", 319 | "SwagCustomizedProductsTemplateConfigurationShareJsonApi", 320 | "SwagCustomizedProductsTemplateExclusion", 321 | "SwagCustomizedProductsTemplateExclusionCondition", 322 | "SwagCustomizedProductsTemplateExclusionConditionJsonApi", 323 | "SwagCustomizedProductsTemplateExclusionConditionValues", 324 | "SwagCustomizedProductsTemplateExclusionJsonApi", 325 | "SwagCustomizedProductsTemplateExclusionOperator", 326 | "SwagCustomizedProductsTemplateExclusionOperatorJsonApi", 327 | "SwagCustomizedProductsTemplateJsonApi", 328 | "SwagCustomizedProductsTemplateOption", 329 | "SwagCustomizedProductsTemplateOptionJsonApi", 330 | "SwagCustomizedProductsTemplateOptionPrice", 331 | "SwagCustomizedProductsTemplateOptionPriceJsonApi", 332 | "SwagCustomizedProductsTemplateOptionValue", 333 | "SwagCustomizedProductsTemplateOptionValueJsonApi", 334 | "SwagCustomizedProductsTemplateOptionValuePrice", 335 | "SwagCustomizedProductsTemplateOptionValuePriceJsonApi", 336 | "SystemConfig", 337 | "SystemConfigJsonApi", 338 | "Tag", 339 | "TagJsonApi", 340 | "Tax", 341 | "TaxJsonApi", 342 | "TaxProvider", 343 | "TaxProviderJsonApi", 344 | "TaxRule", 345 | "TaxRuleJsonApi", 346 | "TaxRuleType", 347 | "TaxRuleTypeJsonApi", 348 | "Theme", 349 | "ThemeChild", 350 | "ThemeJsonApi", 351 | "ThemeMedia", 352 | "ThemeSalesChannel", 353 | "Unit", 354 | "UnitJsonApi", 355 | "User", 356 | "UserAccessKey", 357 | "UserAccessKeyJsonApi", 358 | "UserConfig", 359 | "UserConfigJsonApi", 360 | "UserJsonApi", 361 | "UserRecovery", 362 | "UserRecoveryJsonApi", 363 | "Webhook", 364 | "WebhookEventLog", 365 | "WebhookEventLogJsonApi", 366 | "WebhookJsonApi", 367 | "attributes", 368 | "businessEventsResponse", 369 | "data", 370 | "error", 371 | "failure", 372 | "flowBuilderActionsResponse", 373 | "info", 374 | "infoConfigResponse", 375 | "jsonapi", 376 | "link", 377 | "linkage", 378 | "links", 379 | "meta", 380 | "pagination", 381 | "relationshipLinks", 382 | "relationshipToMany", 383 | "relationshipToOne", 384 | "relationships", 385 | "resource", 386 | "success" 387 | ] 388 | } 389 | -------------------------------------------------------------------------------- /docs/concepts/endpoint-structure/writing-entities/associations.md: -------------------------------------------------------------------------------- 1 | # Associations 2 | 3 | The Admin API allows you to create several data records simultaneously within one request. This is possible by using associations. For example, when a product is written, the prices can be written at the same time. This is not limited to entities that are directly related to the main entity but can be continued for as long as you wish and another association is defined. 4 | 5 | > When writing association via API the following applies: Only data is written, not deleted. So writing a `OneToMany` or `ManyToMany` association only adds new data, the existing data will not be deleted. 6 | > 7 | > When writing a field or association, the API expects the format that it returns when reading the record. 8 | > 9 | > If no ID is given for an association, the API creates a new record 10 | 11 | ## ManyToMany Associations 12 | 13 | `ManyToMany` Associations is an association which is supposed to link two independent entities. The table that serves as the mapping table for the relationship contains only the foreign keys for the entities to be linked. An example: 14 | 15 | * The `ProductEntity` has a `ManyToMany` association with the `CategoryEntity` 16 | * The association is available under the property `categories` 17 | * The data for this association is stored in the `product_category` table. 18 | 19 | There are three ways in which `ManyToMany` associations can be used in the API 20 | 21 | **1: The entity to be linked should be created in the same request.** 22 | 23 | In this case all required fields are sent with the entity. 24 | 25 | ```sample http 26 | { 27 | "method": "PATCH", 28 | "url": "http://localhost/api/product/b7d2554b0ce847cd82f3ac9bd1c0dfca", 29 | "headers": { 30 | "Content-Type": "application/json", 31 | "Accept": "application/json", 32 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 33 | }, 34 | "body": { 35 | "id": "b7d2554b0ce847cd82f3ac9bd1c0dfca", 36 | "categories": [ 37 | { "name": "First category" }, 38 | { "name": "Second category" }, 39 | { "name": "Third category" } 40 | ] 41 | } 42 | } 43 | ``` 44 | 45 | **2: The entity to be linked should be updated in the same request.** 46 | 47 | In this case, the entity already exists in the system, but it can be updated in the same request like all other associations. For this purpose, the corresponding ID of the entity is sent with the request. If the ID does not exist in the system, the API creates a new entity with this id. 48 | 49 | ```sample http 50 | { 51 | "method": "PATCH", 52 | "url": "http://localhost/api/product/b7d2554b0ce847cd82f3ac9bd1c0dfca", 53 | "headers": { 54 | "Content-Type": "application/json", 55 | "Accept": "application/json", 56 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 57 | }, 58 | "body": { 59 | "id": "b7d2554b0ce847cd82f3ac9bd1c0dfca", 60 | "categories": [ 61 | { "id": "98432def39fc4624b33213a56b8c944d", "name": "First category" }, 62 | { "id": "2fbb5fe2e29a4d70aa5854ce7ce3e20b", "name": "Second category" }, 63 | { "id": "b7d2554b0ce847cd82f3ac9bd1c0dfca", "name": "Third category" } 64 | ] 65 | } 66 | } 67 | ``` 68 | 69 | **3: Records should only be linked** _**\(performant\)**_ 70 | 71 | If both data records already exist in the system and are to be linked to the PATCH request exclusively, it is recommended that you send only the ID of the entity. This has the advantage that there is no update of the linked entity, which means less load on the system: 72 | 73 | ```sample http 74 | { 75 | "method": "PATCH", 76 | "url": "http://localhost/api/product/b7d2554b0ce847cd82f3ac9bd1c0dfca", 77 | "headers": { 78 | "Content-Type": "application/json", 79 | "Accept": "application/json", 80 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 81 | }, 82 | "body": { 83 | "id": "b7d2554b0ce847cd82f3ac9bd1c0dfca", 84 | "categories": [ 85 | { "id": "98432def39fc4624b33213a56b8c944d" }, 86 | { "id": "2fbb5fe2e29a4d70aa5854ce7ce3e20b" }, 87 | { "id": "b7d2554b0ce847cd82f3ac9bd1c0dfca" } 88 | ] 89 | } 90 | } 91 | ``` 92 | 93 | ## ManyToOne Associations 94 | 95 | `ManyToOne` associations are associations where the foreign key is stored in the root entity. An example: 96 | 97 | * The `ProductEntity` has a `ManyToOneAssociation` to `ProductManufacturerEntity` 98 | * The association is available under the property `manufacturer` 99 | * The foreign key is stored in the property `manufacturerId`. 100 | 101 | There are three ways in which `ManyToOne` associations can be used in the API 102 | 103 | **1: The entity to be linked is to be created directly with** 104 | 105 | In this case all required fields of the entity must be given: 106 | 107 | ```sample http 108 | { 109 | "method": "PATCH", 110 | "url": "http://localhost/api/product/b7d2554b0ce847cd82f3ac9bd1c0dfca", 111 | "headers": { 112 | "Content-Type": "application/json", 113 | "Accept": "application/json", 114 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 115 | }, 116 | "body": { 117 | "id": "b7d2554b0ce847cd82f3ac9bd1c0dfca", 118 | "manufacturer": { 119 | "name": "My manufacturer" 120 | } 121 | } 122 | } 123 | ``` 124 | 125 | With the above payload, the system creates a new manufacturer in the system and links it to the product `b7d2554b0ce847cd82f3ac9bd1c0dfca`. 126 | 127 | **2: The entity to be linked should be updated in the same request.** 128 | 129 | In this case it is necessary to send the ID of the existing entity. 130 | 131 | ```sample http 132 | { 133 | "method": "PATCH", 134 | "url": "http://localhost/api/product/b7d2554b0ce847cd82f3ac9bd1c0dfca", 135 | "headers": { 136 | "Content-Type": "application/json", 137 | "Accept": "application/json", 138 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 139 | }, 140 | "body": { 141 | "id": "b7d2554b0ce847cd82f3ac9bd1c0dfca", 142 | "manufacturer": { 143 | "id": "98432def39fc4624b33213a56b8c944d", 144 | "name": "My manufacturer" 145 | } 146 | } 147 | } 148 | ``` 149 | 150 | With the above payload, the system first checks whether a manufacturer with the id `98432def39fc4624b33213a56b8c944d` exists. If this is not the case, a new manufacturer with this ID is created. If the manufacturer already exists, the name of the manufacturer is updated. Then the manufacturer will be linked to the product. 151 | 152 | **3: The entity should be linked exclusively** _\(performant\)_ 153 | 154 | With this option, the manufacturer already exists and should only be linked with the product. For this, either only the `id` can be sent, or the foreign key can be specified directly: 155 | 156 | ```sample http 157 | { 158 | "method": "PATCH", 159 | "url": "http://localhost/api/product/b7d2554b0ce847cd82f3ac9bd1c0dfca", 160 | "headers": { 161 | "Content-Type": "application/json", 162 | "Accept": "application/json", 163 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 164 | }, 165 | "body": { 166 | "id": "b7d2554b0ce847cd82f3ac9bd1c0dfca", 167 | "manufacturer": { 168 | "id": "98432def39fc4624b33213a56b8c944d" 169 | } 170 | } 171 | } 172 | ``` 173 | 174 | ```sample http 175 | { 176 | "method": "PATCH", 177 | "url": "http://localhost/api/product/b7d2554b0ce847cd82f3ac9bd1c0dfca", 178 | "headers": { 179 | "Content-Type": "application/json", 180 | "Accept": "application/json", 181 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 182 | }, 183 | "body": { 184 | "id": "b7d2554b0ce847cd82f3ac9bd1c0dfca", 185 | "manufacturerId": "98432def39fc4624b33213a56b8c944d" 186 | } 187 | } 188 | ``` 189 | 190 | Both payloads lead to the same result. This type of use is preferable because only the product entity is updated and not the manufacturer entity with every product update, which leads to less load on the server. 191 | 192 | ## OneToMany Associations 193 | 194 | Unlike the `ManyToOne` and `ManyToMany` association, data in a `OneToMany` association is usually not data that should be linked, but data that belongs to the main entity. This association is the counterpart of the `ManyToOne` association. The foreign key is therefore located in the table of the entity to which the association refers. 195 | 196 | For example: 197 | 198 | * The `CountryEntity` has a `OneToMany` association with the `CountryStateEntity` 199 | * The association is available under the `states` property 200 | * The foreign key is located in the `CountryStateEntity::countryId` property. 201 | 202 | There are two ways to use `OneToMany` associations in the API. 203 | 204 | **1: A new record should be created in the association.** 205 | 206 | In this case all fields marked as required must be given. An ID can also be given here if it is not to be generated on server side: 207 | 208 | ```sample http 209 | { 210 | "method": "POST", 211 | "url": "http://localhost/api/country", 212 | "headers": { 213 | "Content-Type": "application/json", 214 | "Accept": "application/json", 215 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 216 | }, 217 | "body": { 218 | "name" : "new country", 219 | "states": [ 220 | { "id": "b7d2554b0ce847cd82f3ac9bd1c0dfca", "name": "state-a", "shortCode": "A" }, 221 | { "name": "state-b", "shortCode": "B" }, 222 | { "name": "state-c", "shortCode": "C" } 223 | ] 224 | } 225 | } 226 | ``` 227 | 228 | **2: An already existing entity of the association has to be updated** 229 | 230 | In this case, it is necessary that the ID of the entity is also given. If this is not done, the system tries to create a new entity: 231 | 232 | ```sample http 233 | { 234 | "method": "PATCH", 235 | "url": "http://localhost/api/country", 236 | "headers": { 237 | "Content-Type": "application/json", 238 | "Accept": "application/json", 239 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 240 | }, 241 | "body": { 242 | "id": "98432def39fc4624b33213a56b8c944d", 243 | "name" : "new country", 244 | "states": [ 245 | { "id": "b7d2554b0ce847cd82f3ac9bd1c0dfca", "name": "new name" } 246 | ] 247 | } 248 | } 249 | ``` 250 | 251 | If an error occurs while writing the data, the API returns a `400 Bad Request` response in which all errors are listed. The affected records and fields can be identified via `source.pointer`: 252 | 253 | ```sample http 254 | { 255 | "method": "POST", 256 | "url": "http://localhost/api/country", 257 | "headers": { 258 | "Content-Type": "application/json", 259 | "Accept": "application/json", 260 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 261 | }, 262 | "body": { 263 | "name" : "new country", 264 | "states": [ 265 | { "name": "state-a", "shortCode": "A" }, 266 | { "name": "state-b", "shortCode": 1 }, 267 | { "name": "state-c" } 268 | ] 269 | } 270 | } 271 | ``` 272 | 273 | ### Error 274 | 275 | ```javascript 276 | { 277 | "errors": [ 278 | { 279 | "status": "400", 280 | "detail": "This value should be of type string.", 281 | "source": { 282 | "pointer": "/0/states/1/shortCode" 283 | } 284 | }, 285 | { 286 | "status": "400", 287 | "detail": "This value should not be blank.", 288 | "source": { 289 | "pointer": "/0/states/2/shortCode" 290 | } 291 | } 292 | ] 293 | } 294 | ``` 295 | 296 | ## Translated Fields 297 | 298 | In Shopware 6 translatable fields of an entity can be written directly at the entity itself. For example, the `name` of a product is a translatable field. If no other language is set per header, the default language of the system is used for reading and writing. When an entity object is created in the system, it must have a translation in the default language of the system. This translation is used as a fallback if the entity is displayed in another language for which there is no translation. When writing an entity, it is possible to write several languages at the same time. This is done via the `translations` association: 299 | 300 | ```sample http 301 | { 302 | "method": "PATCH", 303 | "url": "http://localhost/api/product/b7d2554b0ce847cd82f3ac9bd1c0dfca", 304 | "headers": { 305 | "Content-Type": "application/json", 306 | "Accept": "application/json", 307 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 308 | }, 309 | "body": { 310 | "id": "b7d2554b0ce847cd82f3ac9bd1c0dfca", 311 | "translations": { 312 | "2fbb5fe2e29a4d70aa5854ce7ce3e20b": { 313 | "name": "english name", 314 | "description": "english description" 315 | }, 316 | "6d7b97a0f3504824bd0e77b021312c33": { 317 | "name": "german name", 318 | "description": "german description" 319 | } 320 | } 321 | } 322 | } 323 | ``` 324 | 325 | Within the `translations` property the language id, for which this translation is used, is then passed as key. All translatable fields can be specified within the object. If the language id is not known, the locale code can be used instead of the id: 326 | 327 | ```sample http 328 | { 329 | "method": "PATCH", 330 | "url": "http://localhost/api/product/b7d2554b0ce847cd82f3ac9bd1c0dfca", 331 | "headers": { 332 | "Content-Type": "application/json", 333 | "Accept": "application/json", 334 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 335 | }, 336 | "body": { 337 | "id": "b7d2554b0ce847cd82f3ac9bd1c0dfca", 338 | "translations": { 339 | "en-GB": { 340 | "name": "english name by code", 341 | "description": "english description by code" 342 | }, 343 | "de-DE": { 344 | "name": "german name by code", 345 | "description": "german description by code" 346 | } 347 | } 348 | } 349 | } 350 | ``` 351 | 352 | Unlike the other types of associations, an update of a translation does not require an ID of the translation entity to be provided. This entities are an exception in the system and are uniquely identified by the language ID. 353 | -------------------------------------------------------------------------------- /docs/guides/quick-start/05-order-management.md: -------------------------------------------------------------------------------- 1 | --- 2 | stoplight-id: fdd24cc76f22d 3 | --- 4 | 5 | # Order Management 6 | 7 | The order resource enables merchants to process orders they receive from customers. 8 | 9 | You can use the orders resource to do the following: 10 | 11 | * Retrieve orders and their line-items 12 | * Create orders 13 | * Update order statuses 14 | * Manage returns 15 | 16 | ## Retrieve Orders 17 | 18 | A list of all customer orders is obtained using the below route: 19 | 20 | ```json http 21 | { 22 | "method": "post", 23 | "url": "/api/search/order", 24 | "headers": { 25 | "Content-Type": "application/json", 26 | "Accept": "application/json", 27 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 28 | } 29 | } 30 | ``` 31 | 32 | [Sorting](https://shopware.stoplight.io/docs/store-api/cf710bf73d0cd-search-queries#sort), [aggregating](https://shopware.stoplight.io/docs/store-api/cf710bf73d0cd-search-queries#aggregations) and [filtering](https://shopware.stoplight.io/docs/store-api/cf710bf73d0cd-search-queries#filter) order results is possible using a [search criteria](https://shopware.stoplight.io/docs/store-api/cf710bf73d0cd-search-queries). 33 | 34 | ### Order line-items 35 | 36 | An order can have other items or child items of `type` - `product`, `promotion`, `credit` or `custom`. To fetch line items for a particular order, try the below route: 37 | 38 | ```json http 39 | { 40 | "method": "get", 41 | "url": "http://localhost/api/order/558efc15fe604829b4d0607df75187e0/line-items", 42 | "headers": { 43 | "Content-Type": "application/json", 44 | "Accept": "application/json", 45 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 46 | } 47 | } 48 | ``` 49 | 50 | ## Create an order 51 | 52 | You can manually create test orders in the admin panel to record orders made outside Shopware or send customer invoices. However, no payments, invoices, etc., are created automatically. 53 | 54 | You can create orders for existing or new customers. 55 | 56 | ```json http 57 | { 58 | "method": "post", 59 | "url": "http://localhost/api/order", 60 | "headers": { 61 | "Content-Type": "application/json", 62 | "Accept": "application/json", 63 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 64 | }, 65 | "body": { 66 | "billingAddressId": "c90e05c82c5a4457844cba7403c7ef96", 67 | "currencyId": "b7d2554b0ce847cd82f3ac9bd1c0dfca", 68 | "languageId": "2fbb5fe2e29a4d70aa5854ce7ce3e20b", 69 | "salesChannelId": "98432def39fc4624b33213a56b8c944d", 70 | "orderDateTime": "2021-05-31T14:13:14.866+00:00", 71 | "currencyFactor": 1.0, 72 | "stateId": "a75eb89b4abe41f9bade83b2f07d874e" 73 | } 74 | } 75 | ``` 76 | 77 | ```json json_schema 78 | { 79 | "type": "object", 80 | "description": "Parameters for order creation.", 81 | "properties": { 82 | "billingAddressId": { 83 | "description": "ID of the billing address.", 84 | "type": "string" 85 | }, 86 | "currencyId": { 87 | "description": "ID of the currency to which the price belongs.", 88 | "type": "string" 89 | }, 90 | "languageId": { 91 | "description": "Unique ID of language.", 92 | "type": "string" 93 | }, 94 | "salesChannelId": { 95 | "description": "Unique ID of the defined sales channel.", 96 | "type": "string" 97 | }, 98 | "orderDateTime": { 99 | "description": "Timestamp of the order placed.", 100 | "type": "string" 101 | }, 102 | "currencyFactor": { 103 | "description": "Rate factor for currencies.", 104 | "type": "string" 105 | }, 106 | "stateId": { 107 | "description": "Unique ID of transition state as defined by the state machine.", 108 | "type": "string" 109 | } 110 | } 111 | } 112 | ``` 113 | 114 | Orders created are associated with payment and delivery transitions. The following section provides you with more details. 115 | 116 | ## Order state handling 117 | 118 | Every order in Shopware has three states `order.state`, `order_delivery.state`, and `order_transaction.state`. For each state, there is a state machine that holds the status of the order, delivery, and payment status, respectively. The `state_machine_transition` is a collection of all defined transitions. 119 | 120 | The `transition` method handles the order transition from one state to another. 121 | 122 | ### Order 123 | 124 | On creating a new order, the order state is set to *open* by default. Order state can be transitioned among `cancel`, `complete`, `reopen`, and `process`. 125 | 126 | Below is a sample request to change the state of order to *complete*: 127 | 128 | ```json http 129 | { 130 | "method": "post", 131 | "url": "http://localhost/api/_action/order/558efc15fe604829b4d0607df75187e0/state/complete", 132 | "headers": { 133 | "Content-Type": "application/json", 134 | "Accept": "application/json", 135 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 136 | }, 137 | "body": { 138 | } 139 | } 140 | ``` 141 | 142 | 143 | > A *cancelled* order cannot change to an *in-progress* state unless it is reopened again. For more details see [order state management](https://developer.shopware.com/docs/concepts/commerce/checkout-concept/orders#state-management) 144 | 145 | ### Order delivery 146 | 147 | The order delivery state represents the state of the delivery. `reopen`, `ship`, `ship_partially`, `cancel`, `retour`, and `retour_partially` are the states associated with order delivery. 148 | 149 | Below is a sample request that sets the delivery state to *fail*: 150 | 151 | ```json http 152 | { 153 | "method": "post", 154 | "url": "http://localhost/api/_action/order_delivery/558efc15fe604829b4d0607df75187e0/state/fail", 155 | "headers": { 156 | "Content-Type": "application/json", 157 | "Accept": "application/json", 158 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 159 | } 160 | } 161 | ``` 162 | 163 | ### Order transaction 164 | 165 | The order transaction state represents the state of the payment. `open`, `fail`, `authorize`, `refund_partially`, `refund`, `do_pay`, `paid`, `paid_partially`, `remind`, and `cancel` are the states associated with order transaction. 166 | 167 | Below is a sample request that sets the payment state to *open*: 168 | 169 | ```json http 170 | { 171 | "method": "post", 172 | "url": "http://localhost/api/_action/order_transaction/558efc15fe604829b4d0607df75187e0/state/open", 173 | "headers": { 174 | "Content-Type": "application/json", 175 | "Accept": "application/json", 176 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 177 | } 178 | } 179 | ``` 180 | 181 | ### Order Return 182 | 183 | The order return management is only supported in Administration. 184 | 185 | #### Create order return 186 | 187 | You can initiate an order return from the Administration section by utilizing the Proxy-api. The outcome will yield a fresh order return with the `created_by_id` set to the ID of the currently logged-in user. 188 | 189 | Below is a sample request to create new order return. 190 | 191 | ```json http 192 | { 193 | "method": "post", 194 | "url": "http://localhost/api/_proxy/order/{orderId}/return", 195 | "headers": { 196 | "Content-Type": "application/json", 197 | "Accept": "application/json", 198 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 199 | }, 200 | "body": { 201 | "lineItems": [ 202 | { 203 | "orderLineItemId": "c90e05c82c5a4457844cba7403c7ef96", 204 | "quantity": 2, 205 | "internalComment": "Line item comment" 206 | } 207 | ], 208 | "internalComment": "Order return comment" 209 | } 210 | } 211 | ``` 212 | 213 | ```description json_schema 214 | { 215 | "type": "object", 216 | "description": "Parameters for adding return line items.", 217 | "properties": { 218 | "lineItems": [] 219 | { 220 | "orderLineItemId": { 221 | "description": "ID of order line item.", 222 | "type": "string" 223 | }, 224 | "quantity": { 225 | "description": "Quantity of order line item which should be returned.", 226 | "type": "integer" 227 | }, 228 | "internalComment": { 229 | "description": "The optional comment when adding line item as return item", 230 | "type": "string" 231 | } 232 | }, 233 | "internalComment": { 234 | "description": "The optional comment when adding line item as return item", 235 | "type": "string" 236 | } 237 | } 238 | } 239 | ``` 240 | 241 | #### Add new order return line items 242 | 243 | If you already have an existing order return, it is indeed possible to include a new item in your return. In the event that the item has already been returned previously, the returned quantity will be increased by the quantity specified in the new return. 244 | 245 | Below is a sample request to add the new item to your return. 246 | 247 | ```json http 248 | { 249 | "method": "post", 250 | "url": "http://localhost/api/_action/order/{orderId}/order-return/{orderReturnId}/add-items", 251 | "headers": { 252 | "Content-Type": "application/json", 253 | "Accept": "application/json", 254 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 255 | }, 256 | "body": { 257 | "orderLineItems": [ 258 | { 259 | "orderLineItemId": "c90e05c82c5a4457844cba7403c7ef96", 260 | "quantity": 2, 261 | "internalComment": "New comment" 262 | } 263 | ] 264 | } 265 | } 266 | ``` 267 | 268 | ```description json_schema 269 | { 270 | "type": "object", 271 | "description": "Parameters for adding return line items.", 272 | "properties": { 273 | "orderLineItems": [] 274 | { 275 | "orderLineItemId": { 276 | "description": "ID of order line item.", 277 | "type": "string" 278 | }, 279 | "quantity": { 280 | "description": "Quantity of order line item which should be returned.", 281 | "type": "integer" 282 | }, 283 | "internalComment": { 284 | "description": "The optional comment when adding line item as return item", 285 | "type": "string" 286 | } 287 | } 288 | } 289 | } 290 | ``` 291 | 292 | #### Order return state transition 293 | 294 | The order return state represents `open`, `cancelled`, `in_progress`, and `done` as transaction states for order items return. 295 | 296 | Below is a sample request that sets the orders return to *open*: 297 | 298 | ```json http 299 | { 300 | "method": "post", 301 | "url": "http://localhost/api/_action/order_return/558efc15fe604829b4d0607df75187e0/state/open", 302 | "headers": { 303 | "Content-Type": "application/json", 304 | "Accept": "application/json", 305 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 306 | } 307 | } 308 | ``` 309 | 310 | #### Order return line item state transition 311 | 312 | The order return line item state represents `open`, `shipped`, `shipped_partially`, `return_requested`, `returned`, `returned_partially`, and `cancelled` as transaction states for order line items return. 313 | 314 | Below is a sample request that sets the order return line item to `open` : 315 | 316 | ```json http 317 | { 318 | "method": "post", 319 | "url": "http://localhost/api/_action/order-line-item/state/open", 320 | "headers": { 321 | "Content-Type": "application/json", 322 | "Accept": "application/json", 323 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 324 | }, 325 | "body": { 326 | "ids": ["558efc15fe604829b4d0607df75187e0"] 327 | } 328 | } 329 | ``` 330 | 331 | ```json json_schema 332 | { 333 | "type": "object", 334 | "description": "Parameters for transitioning order return line item state.", 335 | "properties": { 336 | "ids": { 337 | "description": "ID of order line item.", 338 | "type": "array" 339 | } 340 | } 341 | } 342 | ``` 343 | 344 | #### Order return calculator 345 | 346 | The purpose of the order return calculator is to determine the total amount of the order return. 347 | 348 | Below is a sample request that calculates the amount of provided order return's ID. 349 | 350 | ```json http 351 | { 352 | "method": "post", 353 | "url": "http://localhost/api/_action/order/return/558efc15fe604829b4d0607df75187e0/calculate", 354 | "headers": { 355 | "Content-Type": "application/json", 356 | "Accept": "application/json", 357 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 358 | } 359 | } 360 | ``` 361 | 362 | #### Obtain customer turnover 363 | 364 | This function is designed to retrieve the turnover figure for a specific customer. The turnover value is calculated as the total order amount minus the total return amount. 365 | 366 | Below is a sample request to get the turnover of a customer: 367 | 368 | ```json http 369 | { 370 | "method": "GET", 371 | "url": "http://localhost/api/_action/customer/558efc15fe604829b4d0607df75187e0/turnover", 372 | "headers": { 373 | "Content-Type": "application/json", 374 | "Accept": "application/json", 375 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 376 | } 377 | } 378 | ``` 379 | 380 | ## Refund Payment 381 | 382 | Initiating and capturing payment is handled by [Store API](https://shopware.stoplight.io/docs/store-api/8218801e50fe5-handling-the-payment), whereas the admin API deals with refund payment. 383 | 384 | The refund payment method can be called only for transactions that are claimed to be successful. 385 | 386 | Generally, refunds are linked to a specific order transaction capture ID. An order can have one or more line items and amounts. Each of these line items signifies refund positions. Based on the number of line items requested for refund, the payment can either be partially or completely refunded. 387 | 388 | 389 | > **Refund handling internals** 390 | > 391 | > To allow easy refund handling, have your payment handler implement the `RefundPaymentHandlerInterface`. Your refund handler implementation will be called with the `refundId` to call the PSP or gateway. 392 | > 393 | > For more information, check our documentation on [implementing payment refund handlers](https://developer.shopware.com/docs/guides/plugins/plugins/checkout/payment/add-payment-plugin#refund-example) 394 | 395 | When you refund a payment, the API will change the refund state to *complete*. If you want to fail the refund in your RefundHandler implementation, simply throw a `RefundException`, and the state of the refund will transition to *fail*. 396 | 397 | > Your payment extensions must write their own captures and refunds into the order_transaction_capture and order_transaction_capture_refund tables, respectively, before calling the refund handler, as the Shopware Core does not carry this out. -------------------------------------------------------------------------------- /SwagDigitalSalesRooms-adminapi.summary.json: -------------------------------------------------------------------------------- 1 | { 2 | "paths": [ 3 | "/_action/dsr/appointment/attendee/{attendeeId}/add-cart-discount", 4 | "/_action/dsr/appointment/attendee/{attendeeId}/add-temp-discount", 5 | "/_action/dsr/appointment/attendee/{attendeeId}/apply-temp-discount", 6 | "/_action/dsr/appointment/attendee/{attendeeId}/last-seen-product-ids", 7 | "/_action/dsr/appointment/attendee/{attendeeId}/load-temp-cart", 8 | "/_action/dsr/appointment/attendee/{attendeeId}/remove", 9 | "/_action/dsr/appointment/attendee/{attendeeId}/remove-temp-discount", 10 | "/_action/dsr/appointment/attendee/{attendeeId}/sw-context-token", 11 | "/_action/dsr/appointment/{appointmentId}/end", 12 | "/_action/dsr/appointment/{appointmentId}/instant-listing", 13 | "/_action/dsr/appointment/{appointmentId}/join-as-guide", 14 | "/_action/dsr/appointment/{appointmentId}/presentation/state", 15 | "/_action/dsr/appointment/{appointmentId}/shopping-lists/{shoppingListId}", 16 | "/_action/dsr/appointment/{appointmentId}/start", 17 | "/_action/dsr/appointment/{appointmentId}/video-room", 18 | "/_action/dsr/appointment/{appointmentId}/widgets/attendee-insights", 19 | "/_action/dsr/appointment/{appointmentId}/widgets/cart-insights", 20 | "/_action/dsr/appointment/{appointmentId}/widgets/cart-statistics", 21 | "/_action/dsr/appointment/{appointmentId}/widgets/last-seen-statistics", 22 | "/_action/dsr/appointment/{appointmentId}/widgets/wishlist-statistics", 23 | "/_action/media/{mediaId}/video-cover", 24 | "/aggregate/dsr-appointment", 25 | "/aggregate/dsr-appointment-attendee", 26 | "/aggregate/dsr-appointment-request", 27 | "/aggregate/dsr-appointment-video-chat", 28 | "/aggregate/dsr-attendee-product-collection", 29 | "/aggregate/dsr-cms-slide", 30 | "/aggregate/dsr-interaction", 31 | "/aggregate/dsr-presentation", 32 | "/aggregate/dsr-presentation-cms-page", 33 | "/dsr-appointment", 34 | "/dsr-appointment-attendee", 35 | "/dsr-appointment-attendee/{id}", 36 | "/dsr-appointment-request", 37 | "/dsr-appointment-request/{id}", 38 | "/dsr-appointment-video-chat", 39 | "/dsr-appointment-video-chat/{id}", 40 | "/dsr-appointment/{id}", 41 | "/dsr-attendee-product-collection", 42 | "/dsr-attendee-product-collection/{id}", 43 | "/dsr-cms-slide", 44 | "/dsr-cms-slide/{id}", 45 | "/dsr-interaction", 46 | "/dsr-interaction/{id}", 47 | "/dsr-presentation", 48 | "/dsr-presentation-cms-page", 49 | "/dsr-presentation-cms-page/{id}", 50 | "/dsr-presentation/{id}", 51 | "/search/dsr-appointment", 52 | "/search/dsr-appointment-attendee", 53 | "/search/dsr-appointment-request", 54 | "/search/dsr-appointment-video-chat", 55 | "/search/dsr-attendee-product-collection", 56 | "/search/dsr-cms-slide", 57 | "/search/dsr-interaction", 58 | "/search/dsr-presentation", 59 | "/search/dsr-presentation-cms-page" 60 | ], 61 | "schemas": [ 62 | "AbstractDynamicPageOpenedPayload", 63 | "AclRole", 64 | "AclRoleJsonApi", 65 | "AclUserRole", 66 | "AddCartDiscountRequestBody", 67 | "AddTempDiscountRequestBody", 68 | "Aggregation", 69 | "AggregationEntity", 70 | "AggregationFilter", 71 | "AggregationHistogram", 72 | "AggregationMetrics", 73 | "AggregationRange", 74 | "AggregationTerms", 75 | "App", 76 | "AppActionButton", 77 | "AppActionButtonJsonApi", 78 | "AppAdministrationSnippet", 79 | "AppAdministrationSnippetJsonApi", 80 | "AppCmsBlock", 81 | "AppCmsBlockJsonApi", 82 | "AppFlowAction", 83 | "AppFlowActionJsonApi", 84 | "AppFlowEvent", 85 | "AppFlowEventJsonApi", 86 | "AppJsonApi", 87 | "AppPaymentMethod", 88 | "AppPaymentMethodJsonApi", 89 | "AppScriptCondition", 90 | "AppScriptConditionJsonApi", 91 | "AppShippingMethod", 92 | "AppShippingMethodJsonApi", 93 | "AppTemplate", 94 | "AppTemplateJsonApi", 95 | "Associations", 96 | "AttendeeInsights", 97 | "BasePresentationSlideData", 98 | "CalculatedPrice", 99 | "Cart", 100 | "CartDelivery", 101 | "CartDeliveryInformation", 102 | "CartDeliveryPosition", 103 | "CartError", 104 | "CartItems", 105 | "CartListPrice", 106 | "CartPriceQuantity", 107 | "CartPriceReference", 108 | "Category", 109 | "CategoryJsonApi", 110 | "CategoryTag", 111 | "CmsBlock", 112 | "CmsBlockJsonApi", 113 | "CmsPage", 114 | "CmsPageJsonApi", 115 | "CmsSection", 116 | "CmsSectionJsonApi", 117 | "CmsSlot", 118 | "CmsSlotJsonApi", 119 | "Country", 120 | "CountryJsonApi", 121 | "CountryState", 122 | "CountryStateJsonApi", 123 | "Criteria", 124 | "Currency", 125 | "CurrencyCountryRounding", 126 | "CurrencyCountryRoundingJsonApi", 127 | "CurrencyJsonApi", 128 | "CustomEntity", 129 | "CustomEntityJsonApi", 130 | "CustomField", 131 | "CustomFieldJsonApi", 132 | "CustomFieldSet", 133 | "CustomFieldSetJsonApi", 134 | "CustomFieldSetRelation", 135 | "CustomFieldSetRelationJsonApi", 136 | "Customer", 137 | "CustomerAddress", 138 | "CustomerAddressJsonApi", 139 | "CustomerGroup", 140 | "CustomerGroupJsonApi", 141 | "CustomerGroupRegistrationSalesChannels", 142 | "CustomerJsonApi", 143 | "CustomerRecovery", 144 | "CustomerRecoveryJsonApi", 145 | "CustomerTag", 146 | "CustomerWishlist", 147 | "CustomerWishlistJsonApi", 148 | "CustomerWishlistProduct", 149 | "CustomerWishlistProductJsonApi", 150 | "DeliveryTime", 151 | "DeliveryTimeJsonApi", 152 | "DiscountLineItemPayload", 153 | "DiscountType", 154 | "Document", 155 | "DocumentBaseConfig", 156 | "DocumentBaseConfigJsonApi", 157 | "DocumentBaseConfigSalesChannel", 158 | "DocumentBaseConfigSalesChannelJsonApi", 159 | "DocumentJsonApi", 160 | "DocumentType", 161 | "DocumentTypeJsonApi", 162 | "DsrAppointment", 163 | "DsrAppointmentAttendee", 164 | "DsrAppointmentAttendeeJsonApi", 165 | "DsrAppointmentJsonApi", 166 | "DsrAppointmentRequest", 167 | "DsrAppointmentRequestJsonApi", 168 | "DsrAppointmentVideoChat", 169 | "DsrAppointmentVideoChatJsonApi", 170 | "DsrAttendeeProductCollection", 171 | "DsrAttendeeProductCollectionJsonApi", 172 | "DsrCmsSlide", 173 | "DsrCmsSlideJsonApi", 174 | "DsrInteraction", 175 | "DsrInteractionJsonApi", 176 | "DsrPresentation", 177 | "DsrPresentationCmsPage", 178 | "DsrPresentationCmsPageJsonApi", 179 | "DsrPresentationJsonApi", 180 | "DynamicPageOpenedPayload", 181 | "DynamicProductListingPageOpenedPayload", 182 | "EqualsFilter", 183 | "Excludes", 184 | "Filters", 185 | "Flow", 186 | "FlowJsonApi", 187 | "FlowSequence", 188 | "FlowSequenceJsonApi", 189 | "FlowTemplate", 190 | "FlowTemplateJsonApi", 191 | "GetAttendeeInsightsResponse", 192 | "GetCartInsightsResponse", 193 | "GetListBodyRequest", 194 | "GuidePresentationStateResponse", 195 | "ImportExportFile", 196 | "ImportExportFileJsonApi", 197 | "ImportExportLog", 198 | "ImportExportLogJsonApi", 199 | "ImportExportProfile", 200 | "ImportExportProfileJsonApi", 201 | "Includes", 202 | "Integration", 203 | "IntegrationJsonApi", 204 | "IntegrationRole", 205 | "JoinAppointmentResponse", 206 | "LandingPage", 207 | "LandingPageJsonApi", 208 | "LandingPageSalesChannel", 209 | "LandingPageTag", 210 | "Language", 211 | "LanguageJsonApi", 212 | "LineItem", 213 | "LineItemType", 214 | "Locale", 215 | "LocaleJsonApi", 216 | "LogEntry", 217 | "LogEntryJsonApi", 218 | "MailHeaderFooter", 219 | "MailHeaderFooterJsonApi", 220 | "MailTemplate", 221 | "MailTemplateJsonApi", 222 | "MailTemplateMedia", 223 | "MailTemplateType", 224 | "MailTemplateTypeJsonApi", 225 | "MainCategory", 226 | "MainCategoryJsonApi", 227 | "MeasurementDisplayUnit", 228 | "MeasurementDisplayUnitJsonApi", 229 | "MeasurementSystem", 230 | "MeasurementSystemJsonApi", 231 | "MeasurementUnits", 232 | "Media", 233 | "MediaDefaultFolder", 234 | "MediaDefaultFolderJsonApi", 235 | "MediaFolder", 236 | "MediaFolderConfiguration", 237 | "MediaFolderConfigurationJsonApi", 238 | "MediaFolderConfigurationMediaThumbnailSize", 239 | "MediaFolderJsonApi", 240 | "MediaJsonApi", 241 | "MediaTag", 242 | "MediaThumbnail", 243 | "MediaThumbnailJsonApi", 244 | "MediaThumbnailSize", 245 | "MediaThumbnailSizeJsonApi", 246 | "MultiNotFilter", 247 | "NewsletterRecipient", 248 | "NewsletterRecipientJsonApi", 249 | "NewsletterRecipientTag", 250 | "Notification", 251 | "NotificationJsonApi", 252 | "NumberRange", 253 | "NumberRangeJsonApi", 254 | "NumberRangeSalesChannel", 255 | "NumberRangeSalesChannelJsonApi", 256 | "NumberRangeState", 257 | "NumberRangeStateJsonApi", 258 | "NumberRangeType", 259 | "NumberRangeTypeJsonApi", 260 | "OAuthClientCredentialsGrant", 261 | "OAuthGrant", 262 | "OAuthPasswordGrant", 263 | "OAuthRefreshTokenGrant", 264 | "OAuthScopes", 265 | "Order", 266 | "OrderAddress", 267 | "OrderAddressJsonApi", 268 | "OrderCustomer", 269 | "OrderCustomerJsonApi", 270 | "OrderDelivery", 271 | "OrderDeliveryJsonApi", 272 | "OrderDeliveryPosition", 273 | "OrderDeliveryPositionJsonApi", 274 | "OrderJsonApi", 275 | "OrderLineItem", 276 | "OrderLineItemDownload", 277 | "OrderLineItemDownloadJsonApi", 278 | "OrderLineItemJsonApi", 279 | "OrderTag", 280 | "OrderTransaction", 281 | "OrderTransactionCapture", 282 | "OrderTransactionCaptureJsonApi", 283 | "OrderTransactionCaptureRefund", 284 | "OrderTransactionCaptureRefundJsonApi", 285 | "OrderTransactionCaptureRefundPosition", 286 | "OrderTransactionCaptureRefundPositionJsonApi", 287 | "OrderTransactionJsonApi", 288 | "PaymentMethod", 289 | "PaymentMethodJsonApi", 290 | "Plugin", 291 | "PluginJsonApi", 292 | "PresentationCmsPage", 293 | "PresentationSlideData", 294 | "Price", 295 | "Product", 296 | "ProductCategory", 297 | "ProductCategoryTree", 298 | "ProductConfiguratorSetting", 299 | "ProductConfiguratorSettingJsonApi", 300 | "ProductCrossSelling", 301 | "ProductCrossSellingAssignedProducts", 302 | "ProductCrossSellingAssignedProductsJsonApi", 303 | "ProductCrossSellingJsonApi", 304 | "ProductCustomFieldSet", 305 | "ProductDownload", 306 | "ProductDownloadJsonApi", 307 | "ProductExport", 308 | "ProductExportJsonApi", 309 | "ProductFeatureSet", 310 | "ProductFeatureSetJsonApi", 311 | "ProductJsonApi", 312 | "ProductKeywordDictionary", 313 | "ProductKeywordDictionaryJsonApi", 314 | "ProductManufacturer", 315 | "ProductManufacturerJsonApi", 316 | "ProductMedia", 317 | "ProductMediaJsonApi", 318 | "ProductOption", 319 | "ProductPrice", 320 | "ProductPriceJsonApi", 321 | "ProductProperty", 322 | "ProductReview", 323 | "ProductReviewJsonApi", 324 | "ProductSearchConfig", 325 | "ProductSearchConfigField", 326 | "ProductSearchConfigFieldJsonApi", 327 | "ProductSearchConfigJsonApi", 328 | "ProductSearchKeyword", 329 | "ProductSearchKeywordJsonApi", 330 | "ProductSorting", 331 | "ProductSortingJsonApi", 332 | "ProductStream", 333 | "ProductStreamFilter", 334 | "ProductStreamFilterJsonApi", 335 | "ProductStreamJsonApi", 336 | "ProductStreamMapping", 337 | "ProductTag", 338 | "ProductVisibility", 339 | "ProductVisibilityJsonApi", 340 | "Promotion", 341 | "PromotionCartRule", 342 | "PromotionDiscount", 343 | "PromotionDiscountJsonApi", 344 | "PromotionDiscountPrices", 345 | "PromotionDiscountPricesJsonApi", 346 | "PromotionDiscountRule", 347 | "PromotionIndividualCode", 348 | "PromotionIndividualCodeJsonApi", 349 | "PromotionJsonApi", 350 | "PromotionOrderRule", 351 | "PromotionPersonaCustomer", 352 | "PromotionPersonaRule", 353 | "PromotionSalesChannel", 354 | "PromotionSalesChannelJsonApi", 355 | "PromotionSetgroup", 356 | "PromotionSetgroupJsonApi", 357 | "PromotionSetgroupRule", 358 | "PropertyGroup", 359 | "PropertyGroupJsonApi", 360 | "PropertyGroupOption", 361 | "PropertyGroupOptionJsonApi", 362 | "RangeFilter", 363 | "Rule", 364 | "RuleCondition", 365 | "RuleConditionJsonApi", 366 | "RuleJsonApi", 367 | "RuleTag", 368 | "SalesChannel", 369 | "SalesChannelAnalytics", 370 | "SalesChannelAnalyticsJsonApi", 371 | "SalesChannelCountry", 372 | "SalesChannelCurrency", 373 | "SalesChannelDomain", 374 | "SalesChannelDomainJsonApi", 375 | "SalesChannelJsonApi", 376 | "SalesChannelLanguage", 377 | "SalesChannelPaymentMethod", 378 | "SalesChannelShippingMethod", 379 | "SalesChannelType", 380 | "SalesChannelTypeJsonApi", 381 | "Salutation", 382 | "SalutationJsonApi", 383 | "ScheduledTask", 384 | "ScheduledTaskJsonApi", 385 | "Script", 386 | "ScriptJsonApi", 387 | "SeoUrl", 388 | "SeoUrlJsonApi", 389 | "SeoUrlTemplate", 390 | "SeoUrlTemplateJsonApi", 391 | "ShippingMethod", 392 | "ShippingMethodJsonApi", 393 | "ShippingMethodPrice", 394 | "ShippingMethodPriceJsonApi", 395 | "ShippingMethodTag", 396 | "SimpleFilter", 397 | "Snippet", 398 | "SnippetJsonApi", 399 | "SnippetSet", 400 | "SnippetSetJsonApi", 401 | "Sort", 402 | "StateForAll", 403 | "StateForGuides", 404 | "StateMachine", 405 | "StateMachineHistory", 406 | "StateMachineHistoryJsonApi", 407 | "StateMachineJsonApi", 408 | "StateMachineState", 409 | "StateMachineStateJsonApi", 410 | "StateMachineTransition", 411 | "StateMachineTransitionJsonApi", 412 | "SubAggregations", 413 | "SystemConfig", 414 | "SystemConfigJsonApi", 415 | "Tag", 416 | "TagJsonApi", 417 | "Tax", 418 | "TaxJsonApi", 419 | "TaxProvider", 420 | "TaxProviderJsonApi", 421 | "TaxRule", 422 | "TaxRuleJsonApi", 423 | "TaxRuleType", 424 | "TaxRuleTypeJsonApi", 425 | "Theme", 426 | "ThemeChild", 427 | "ThemeJsonApi", 428 | "ThemeMedia", 429 | "ThemeSalesChannel", 430 | "Unit", 431 | "UnitJsonApi", 432 | "User", 433 | "UserAccessKey", 434 | "UserAccessKeyJsonApi", 435 | "UserConfig", 436 | "UserConfigJsonApi", 437 | "UserJsonApi", 438 | "UserRecovery", 439 | "UserRecoveryJsonApi", 440 | "VideoChatCreateStruct", 441 | "Webhook", 442 | "WebhookEventLog", 443 | "WebhookEventLogJsonApi", 444 | "WebhookJsonApi", 445 | "WidgetProductListing", 446 | "attributes", 447 | "businessEventsResponse", 448 | "data", 449 | "error", 450 | "failure", 451 | "flowBuilderActionsResponse", 452 | "info", 453 | "infoConfigResponse", 454 | "jsonapi", 455 | "link", 456 | "linkage", 457 | "links", 458 | "meta", 459 | "pagination", 460 | "relationshipLinks", 461 | "relationshipToMany", 462 | "relationshipToOne", 463 | "relationships", 464 | "resource", 465 | "success" 466 | ] 467 | } 468 | -------------------------------------------------------------------------------- /docs/concepts/endpoint-structure/writing-entities/product-data.md: -------------------------------------------------------------------------------- 1 | # Product Data 2 | 3 | Refer to [Product Management](../../../guides/quick-start/02-product-management.md) section of this guide to get an overview of how the product data is handled. 4 | 5 | Next, let us understand more about how media, variants etc. are handled for the product entity. 6 | 7 | ## Media Management 8 | 9 | > **Upload media resources** 10 | > 11 | > Please go to our guide on [Media Management](../media-handling.md) to get detailed information on uploading media. The section below only deals with the data model e.g. setting covers or ordering images. 12 | 13 | Media of products are maintained via the association `product.media` and `product.cover`. The `product.media` association is a `one-to-many` association on the `product_media` entity. To assign a media to a product, a new `product_media` entity must be created, in which the foreign key for the corresponding `media` entity is defined. In addition to the foreign key, a `position` can be specified, which defines the display order. 14 | 15 | 16 | ```sample http 17 | { 18 | "method": "POST", 19 | "url": "http://localhost/api/product", 20 | "headers": { 21 | "Content-Type": "application/json", 22 | "Accept": "application/json", 23 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 24 | }, 25 | "body": { 26 | "name": "test", 27 | "productNumber": "random", 28 | "stock": 10, 29 | "taxId": "5f78f2d4b19f49648eb1b38881463da0", 30 | "price": [ 31 | { "currencyId" : "b7d2554b0ce847cd82f3ac9bd1c0dfca", "gross": 15, "net": 10, "linked" : false } 32 | ], 33 | "media": [ 34 | { 35 | "id": "5f78f2d4b19f49648eb1b38881463da0", 36 | "mediaId": "00a9742db2e643ccb9d969f5a30c2758", 37 | "position": 1 38 | } 39 | ] 40 | } 41 | } 42 | ``` 43 | 44 | To delete a media assignment, the ID of the `product_media` entity is required. In the above case this is the `5f78f2d4b19f49648eb1b38881463da0`. The corresponding route `DELETE /api/product/{productId}/media/{productMediaId}` can be used for this. To delete multiple assignments, the `/_action/sync` route can also be used here: 45 | 46 | > The key "unassign-media" can be defined individually 47 | 48 | ```sample http 49 | { 50 | "method": "POST", 51 | "url": "http://localhost/api/product", 52 | "headers": { 53 | "Content-Type": "application/json", 54 | "Accept": "application/json", 55 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 56 | }, 57 | "body": { 58 | "unassign-media": { 59 | "entity": "product_media", 60 | "action": "delete", 61 | "payload": [ 62 | { "id": "5f78f2d4b19f49648eb1b38881463da0" }, 63 | { "id": "18ada8e085d240369d06bb4b11eed3b5" } 64 | ] 65 | } 66 | } 67 | } 68 | ``` 69 | 70 | ### Setting the cover 71 | 72 | The `cover` of a product is controlled via `coverId` and the `cover` association. This contains a direct reference to a `product_media` entity. To set the cover of a product the following payload can be used: 73 | 74 | ```sample http 75 | { 76 | "method": "PATCH", 77 | "url": "http://localhost/api/product/0fa91ce3e96a4bc2be4bd9ce752c3425", 78 | "headers": { 79 | "Content-Type": "application/json", 80 | "Accept": "application/json", 81 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 82 | }, 83 | "body": { 84 | "coverId": "00a9742db2e643ccb9d969f5a30c2758" 85 | } 86 | } 87 | ``` 88 | 89 | To reset the cover, the value `null` can be passed instead of a UUID. 90 | 91 | ## Visibility handling 92 | 93 | The `visibilities` control in which sales channel the product should be visible. This association is a `one-to-many` association. 94 | 95 | Instead of just assigning a sales channel, the data structure allows a specification where the product should be displayed inside the sales channel using the `visibility` property. 96 | 97 | This can be set to three different values: 98 | 99 | | **Visibility** | **Behaviour** | 100 | | :--- |:------------------------------------------------------------------------------------------------------| 101 | | 10 | The product is only available via a direct link. It does **not** appear in listings or searches. | 102 | | 20 | The product is only available via a direct link and search. The product is **not** displayed in listings. | 103 | | 30 | The product is displayed **everywhere**. | 104 | 105 | Since visibility can be configured per sales channel, the entity also has its own ID. This is needed to delete or update the assignment later. To assign a product to several sales channels, the following payload can be used: 106 | 107 | ```sample http 108 | { 109 | "method": "POST", 110 | "url": "http://localhost/api/product", 111 | "headers": { 112 | "Content-Type": "application/json", 113 | "Accept": "application/json", 114 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 115 | }, 116 | "body": { 117 | "name": "test", 118 | "productNumber": "random", 119 | "stock": 10, 120 | "taxId": "5f78f2d4b19f49648eb1b38881463da0", 121 | "price": [ 122 | { "currencyId" : "b7d2554b0ce847cd82f3ac9bd1c0dfca", "gross": 15, "net": 10, "linked" : false } 123 | ], 124 | "visibilities": [ 125 | { "id": "5f78f2d4b19f49648eb1b38881463da0", "salesChannelId": "98432def39fc4624b33213a56b8c944d", "visibility": 20 }, 126 | { "id": "b7d2554b0ce847cd82f3ac9bd1c0dfca", "salesChannelId": "ddcb57c32d6e4b598d8b6082a9ca7b42", "visibility": 30 } 127 | ] 128 | } 129 | } 130 | ``` 131 | 132 | Deleting a sales channel assignment is done via the route `/api/product/{productId}/visibilities/{visibilityId}`. To delete several assignments at once, the `/_action/sync` route can be used: 133 | 134 | ```sample http 135 | { 136 | "method": "DELETE", 137 | "url": "http://localhost/api/product/{productId}/visibilities/{visibilityId}", 138 | "headers": { 139 | "Content-Type": "application/json", 140 | "Accept": "application/json", 141 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 142 | }, 143 | "body": { 144 | "unassign-sales-channel-visibilities": { 145 | "entity": "product_visibility", 146 | "action": "delete", 147 | "payload": [ 148 | { "id": "5f78f2d4b19f49648eb1b38881463da0" }, 149 | { "id": "b7d2554b0ce847cd82f3ac9bd1c0dfca" } 150 | ] 151 | } 152 | } 153 | } 154 | ``` 155 | 156 | ## Variant handling 157 | 158 | Variants are child elements of a product. As soon as a product is configured with variants, the parent product is only a kind of container. To create a variant, the following properties are required: 159 | 160 | * `parentId` \[string\] - Defines for which product the variant should be created 161 | * `stock` \[int\] - Defines the stock of the variant 162 | * `productNumber` \[string\] - Defines the unique product number 163 | * `options` \[array\] - Defines the characteristic of the variant. 164 | 165 | ```sample http 166 | { 167 | "method": "POST", 168 | "url": "http://localhost/api/product", 169 | "headers": { 170 | "Content-Type": "application/json", 171 | "Accept": "application/json", 172 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 173 | }, 174 | "body": { 175 | "id": "0d0adf2a3aa1488eb177288cfac9d47e", 176 | "parentId": "17f255e0a12848c38b7ec6767a6d6adf", 177 | "productNumber": "child.1", 178 | "stock": 10, 179 | "options": [ 180 | {"id": "0584efb5f86142aaac44cc3beeeeb84f"}, 181 | {"id": "0a30f132eb1b4f34a05dcb1c6493ced7"} 182 | ] 183 | } 184 | } 185 | ``` 186 | 187 | ```javascript 188 | { 189 | "options": [ 190 | {"id": "0584efb5f86142aaac44cc3beeeeb84f"}, // red 191 | {"id": "0a30f132eb1b4f34a05dcb1c6493ced7"} // xl 192 | ] 193 | } 194 | ``` 195 | 196 | ## Inheritance 197 | 198 | Data that is not defined in a variant, is inherited from the parent product. If the variants have not defined their own `price`, the `price` of the parent product is displayed. This logic applies to different fields, but also to associations like `product.prices`, `product.categories` and many more. 199 | 200 | To define a separate `price` for a variant, the same payload can be used as for a non-variant products: 201 | 202 | ```sample http 203 | { 204 | "method": "POST", 205 | "url": "http://localhost/api/product", 206 | "headers": { 207 | "Content-Type": "application/json", 208 | "Accept": "application/json", 209 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 210 | }, 211 | "body": { 212 | "id": "0d0adf2a3aa1488eb177288cfac9d47e", 213 | "parentId": "17f255e0a12848c38b7ec6767a6d6adf", 214 | "productNumber": "child.1", 215 | "stock": 10, 216 | "options": [ 217 | {"id": "0584efb5f86142aaac44cc3beeeeb84f"}, 218 | {"id": "0a30f132eb1b4f34a05dcb1c6493ced7"} 219 | ], 220 | "price": [ 221 | { "currencyId" : "b7d2554b0ce847cd82f3ac9bd1c0dfca", "gross": 15, "net": 10, "linked" : false } 222 | ] 223 | } 224 | } 225 | ``` 226 | 227 | To restore inheritance, the value `null` can be passed for simple data fields: 228 | 229 | ```sample http 230 | { 231 | "method": "PATCH", 232 | "url": "http://localhost/api/product/0fa91ce3e96a4bc2be4bd9ce752c3425", 233 | "headers": { 234 | "Content-Type": "application/json", 235 | "Accept": "application/json", 236 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 237 | }, 238 | "body": { 239 | "price": null 240 | } 241 | } 242 | ``` 243 | 244 | In order to have an association such as `product.prices` inherited again from the parent product, the corresponding entities must be deleted. 245 | 246 | If a variant is read via `/api`, only the not inherited data is returned. The data of the parent is not loaded here. In the `store-api`, however, the variant is always read with the inheritance, so that all information is already available to display the variant in a shop. 247 | 248 | However, it is also possible to resolve the inheritance in the `/api` by providing the `sw-inheritance` header. 249 | 250 | ## Configurator handling 251 | 252 | To create a complete product with variants, not only the variants have to be created but also the corresponding `options` have to be configured. For the variants this is done via the `options` association. This association defines the characteristics of the variant, i.e. whether it is the yellow or red t-shirt. For the parent product, the `configuratorSettings` association must be defined. This defines which options are generally available. The Admin UI and the Storefront UI are built using this data. The following payload can be used to generate a product with the variants: red-xl, red-l, yellow-xl, yellow-l. 253 | 254 | ```sample http 255 | { 256 | "method": "POST", 257 | "url": "http://localhost/api/product", 258 | "headers": { 259 | "Content-Type": "application/json", 260 | "Accept": "application/json", 261 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 262 | }, 263 | "body": { 264 | "stock": 10, 265 | "productNumber": "random", 266 | "name": "random", 267 | "taxId": "9d4a11eeaf3a41bea44fdfb599d57058", 268 | "price": [ 269 | { 270 | "currencyId": "b7d2554b0ce847cd82f3ac9bd1c0dfca", 271 | "net": 1, 272 | "gross": 1, 273 | "linked": true 274 | } 275 | ], 276 | "variantListingConfig": { 277 | "configuratorGroupConfig": [ 278 | { 279 | "id": "d1f3079ffea34441b0b3e3096ac4821a", 280 | "representation": "box", 281 | "expressionForListings": true 282 | }, 283 | { 284 | "id": "e2d24e55b56b4a4a8f808478fbd30333", 285 | "representation": "box", 286 | "expressionForListings": false 287 | } 288 | ] 289 | }, 290 | "children": [ 291 | { 292 | "productNumber": "random.4", 293 | "stock": 10, 294 | "price": [ 295 | { 296 | "currencyId": "b7d2554b0ce847cd82f3ac9bd1c0dfca", 297 | "net": 1, 298 | "gross": 1, 299 | "linked": true 300 | } 301 | ], 302 | "options": [ 303 | { "id": "4053fb11b4114d2cac7381c904651b6b" }, 304 | { "id": "ae821a4395f34b22b6dea9963c7406f2" } 305 | ] 306 | }, 307 | { 308 | "productNumber": "random.3", 309 | "stock": 10, 310 | "options": [ 311 | { "id": "ea14a701771148d6b04045f99c502829" }, 312 | { "id": "ae821a4395f34b22b6dea9963c7406f2" } 313 | ] 314 | }, 315 | { 316 | "productNumber": "random.1", 317 | "stock": 10, 318 | "options": [ 319 | { "id": "ea14a701771148d6b04045f99c502829" }, 320 | { "id": "0b9627a94fc2446498ec6abac0f03581" } 321 | ] 322 | }, 323 | { 324 | "productNumber": "random.2", 325 | "stock": 10, 326 | "options": [ 327 | { "id": "4053fb11b4114d2cac7381c904651b6b" }, 328 | { "id": "0b9627a94fc2446498ec6abac0f03581" } 329 | ] 330 | } 331 | ], 332 | "configuratorSettings": [ 333 | { "optionId": "0b9627a94fc2446498ec6abac0f03581" }, 334 | { "optionId": "4053fb11b4114d2cac7381c904651b6b" }, 335 | { "optionId": "ae821a4395f34b22b6dea9963c7406f2" }, 336 | { "optionId": "ea14a701771148d6b04045f99c502829" } 337 | ] 338 | } 339 | } 340 | ``` 341 | 342 | ```javascript 343 | // Payload with comments 344 | 345 | { 346 | "stock": 10, 347 | "productNumber": "random", 348 | "name": "random", 349 | "taxId": "9d4a11eeaf3a41bea44fdfb599d57058", 350 | "price": [ 351 | { 352 | "currencyId": "b7d2554b0ce847cd82f3ac9bd1c0dfca", 353 | "net": 1, 354 | "gross": 1, 355 | "linked": true 356 | } 357 | ], 358 | "variantListingConfig": { 359 | "configuratorGroupConfig": [ 360 | { 361 | "id": "d1f3079ffea34441b0b3e3096ac4821a", 362 | "representation": "box", 363 | "expressionForListings": true 364 | }, 365 | { 366 | "id": "e2d24e55b56b4a4a8f808478fbd30333", 367 | "representation": "box", 368 | "expressionForListings": false 369 | } 370 | ] 371 | }, 372 | "children": [ 373 | { 374 | "productNumber": "random.4", 375 | "stock": 10, 376 | // own pricing 377 | "price": [ 378 | { 379 | "currencyId": "b7d2554b0ce847cd82f3ac9bd1c0dfca", 380 | "net": 1, 381 | "gross": 1, 382 | "linked": true 383 | } 384 | ], 385 | "options": [ 386 | { "id": "4053fb11b4114d2cac7381c904651b6b" }, // size: L 387 | { "id": "ae821a4395f34b22b6dea9963c7406f2" } // color: yellow 388 | ] 389 | }, 390 | { 391 | "productNumber": "random.3", 392 | "stock": 10, 393 | "options": [ 394 | { "id": "ea14a701771148d6b04045f99c502829" }, // size: XL 395 | { "id": "ae821a4395f34b22b6dea9963c7406f2" } // color: yellow 396 | ] 397 | }, 398 | { 399 | "productNumber": "random.1", 400 | "stock": 10, 401 | "options": [ 402 | { "id": "ea14a701771148d6b04045f99c502829" }, // size: XL 403 | { "id": "0b9627a94fc2446498ec6abac0f03581" } // color: red 404 | ] 405 | }, 406 | { 407 | "productNumber": "random.2", 408 | "stock": 10, 409 | "options": [ 410 | { "id": "4053fb11b4114d2cac7381c904651b6b" }, // size: L 411 | { "id": "0b9627a94fc2446498ec6abac0f03581" } // color: red 412 | ] 413 | } 414 | ], 415 | "configuratorSettings": [ 416 | { "optionId": "0b9627a94fc2446498ec6abac0f03581" }, // color: red 417 | { "optionId": "4053fb11b4114d2cac7381c904651b6b" }, // size: L 418 | { "optionId": "ae821a4395f34b22b6dea9963c7406f2" }, // color: yellow 419 | { "optionId": "ea14a701771148d6b04045f99c502829" } // size: XL 420 | ] 421 | } 422 | ``` 423 | -------------------------------------------------------------------------------- /docs/resources/entity-reference.md: -------------------------------------------------------------------------------- 1 | # Entity Reference 2 | 3 | > Below, you find a list of all entities provided by the Shopware Core. You can use these as a reference to structure your API requests and find out how fields are named, structured and which ones are required etc. 4 | 5 | | Entity Name | API Path | 6 | | --- | --- | 7 | | [AclRole](../../adminapi.json/components/schemas/AclRole) | `/api/acl-role` | 8 | | [AclUserRole](../../adminapi.json/components/schemas/AclUserRole) | `/api/acl-user-role` | 9 | | [App](../../adminapi.json/components/schemas/App) | `/api/app` | 10 | | [AppActionButton](../../adminapi.json/components/schemas/AppActionButton) | `/api/app-action-button` | 11 | | [AppPaymentMethod](../../adminapi.json/components/schemas/AppPaymentMethod) | `/api/app-payment-method` | 12 | | [AppTemplate](../../adminapi.json/components/schemas/AppTemplate) | `/api/app-template` | 13 | | [Category](../../adminapi.json/components/schemas/Category) | `/api/category` | 14 | | [CategoryTag](../../adminapi.json/components/schemas/CategoryTag) | `/api/category-tag` | 15 | | [CmsBlock](../../adminapi.json/components/schemas/CmsBlock) | `/api/cms-block` | 16 | | [CmsPage](../../adminapi.json/components/schemas/CmsPage) | `/api/cms-page` | 17 | | [CmsSection](../../adminapi.json/components/schemas/CmsSection) | `/api/cms-section` | 18 | | [CmsSlot](../../adminapi.json/components/schemas/CmsSlot) | `/api/cms-slot` | 19 | | [Country](../../adminapi.json/components/schemas/Country) | `/api/country` | 20 | | [CountryState](../../adminapi.json/components/schemas/CountryState) | `/api/country-state` | 21 | | [Currency](../../adminapi.json/components/schemas/Currency) | `/api/currency` | 22 | | [CurrencyCountryRounding](../../adminapi.json/components/schemas/CurrencyCountryRounding) | `/api/currency-country-rounding` | 23 | | [CustomField](../../adminapi.json/components/schemas/CustomField) | `/api/custom-field` | 24 | | [CustomFieldSet](../../adminapi.json/components/schemas/CustomFieldSet) | `/api/custom-field-set` | 25 | | [CustomFieldSetRelation](../../adminapi.json/components/schemas/CustomFieldSetRelation) | `/api/custom-field-set-relation` | 26 | | [Customer](../../adminapi.json/components/schemas/Customer) | `/api/customer` | 27 | | [CustomerAddress](../../adminapi.json/components/schemas/CustomerAddress) | `/api/customer-address` | 28 | | [CustomerGroup](../../adminapi.json/components/schemas/CustomerGroup) | `/api/customer-group` | 29 | | [CustomerGroupRegistrationSalesChannels](../../adminapi.json/components/schemas/CustomerGroupRegistrationSalesChannels) | `/api/customer-group-registration-sales-channels` | 30 | | [CustomerRecovery](../../adminapi.json/components/schemas/CustomerRecovery) | `/api/customer-recovery` | 31 | | [CustomerTag](../../adminapi.json/components/schemas/CustomerTag) | `/api/customer-tag` | 32 | | [CustomerWishlist](../../adminapi.json/components/schemas/CustomerWishlist) | `/api/customer-wishlist` | 33 | | [CustomerWishlistProduct](../../adminapi.json/components/schemas/CustomerWishlistProduct) | `/api/customer-wishlist-product` | 34 | | [DeadMessage](../../adminapi.json/components/schemas/DeadMessage) | `/api/dead-message` | 35 | | [DeliveryTime](../../adminapi.json/components/schemas/DeliveryTime) | `/api/delivery-time` | 36 | | [Document](../../adminapi.json/components/schemas/Document) | `/api/document` | 37 | | [DocumentBaseConfig](../../adminapi.json/components/schemas/DocumentBaseConfig) | `/api/document-base-config` | 38 | | [DocumentBaseConfigSalesChannel](../../adminapi.json/components/schemas/DocumentBaseConfigSalesChannel) | `/api/document-base-config-sales-channel` | 39 | | [DocumentType](../../adminapi.json/components/schemas/DocumentType) | `/api/document-type` | 40 | | [EventAction](../../adminapi.json/components/schemas/EventAction) | `/api/event-action` | 41 | | [EventActionRule](../../adminapi.json/components/schemas/EventActionRule) | `/api/event-action-rule` | 42 | | [EventActionSalesChannel](../../adminapi.json/components/schemas/EventActionSalesChannel) | `/api/event-action-sales-channel` | 43 | | [ImportExportFile](../../adminapi.json/components/schemas/ImportExportFile) | `/api/import-export-file` | 44 | | [ImportExportLog](../../adminapi.json/components/schemas/ImportExportLog) | `/api/import-export-log` | 45 | | [ImportExportProfile](../../adminapi.json/components/schemas/ImportExportProfile) | `/api/import-export-profile` | 46 | | [Integration](../../adminapi.json/components/schemas/Integration) | `/api/integration` | 47 | | [IntegrationRole](../../adminapi.json/components/schemas/IntegrationRole) | `/api/integration-role` | 48 | | [LandingPage](../../adminapi.json/components/schemas/LandingPage) | `/api/landing-page` | 49 | | [LandingPageSalesChannel](../../adminapi.json/components/schemas/LandingPageSalesChannel) | `/api/landing-page-sales-channel` | 50 | | [LandingPageTag](../../adminapi.json/components/schemas/LandingPageTag) | `/api/landing-page-tag` | 51 | | [Language](../../adminapi.json/components/schemas/Language) | `/api/language` | 52 | | [Locale](../../adminapi.json/components/schemas/Locale) | `/api/locale` | 53 | | [LogEntry](../../adminapi.json/components/schemas/LogEntry) | `/api/log-entry` | 54 | | [MailHeaderFooter](../../adminapi.json/components/schemas/MailHeaderFooter) | `/api/mail-header-footer` | 55 | | [MailTemplate](../../adminapi.json/components/schemas/MailTemplate) | `/api/mail-template` | 56 | | [MailTemplateMedia](../../adminapi.json/components/schemas/MailTemplateMedia) | `/api/mail-template-media` | 57 | | [MailTemplateType](../../adminapi.json/components/schemas/MailTemplateType) | `/api/mail-template-type` | 58 | | [MainCategory](../../adminapi.json/components/schemas/MainCategory) | `/api/main-category` | 59 | | [Media](../../adminapi.json/components/schemas/Media) | `/api/media` | 60 | | [MediaDefaultFolder](../../adminapi.json/components/schemas/MediaDefaultFolder) | `/api/media-default-folder` | 61 | | [MediaFolder](../../adminapi.json/components/schemas/MediaFolder) | `/api/media-folder` | 62 | | [MediaFolderConfiguration](../../adminapi.json/components/schemas/MediaFolderConfiguration) | `/api/media-folder-configuration` | 63 | | [MediaFolderConfigurationMediaThumbnailSize](../../adminapi.json/components/schemas/MediaFolderConfigurationMediaThumbnailSize) | `/api/media-folder-configuration-media-thumbnail-size` | 64 | | [MediaTag](../../adminapi.json/components/schemas/MediaTag) | `/api/media-tag` | 65 | | [MediaThumbnail](../../adminapi.json/components/schemas/MediaThumbnail) | `/api/media-thumbnail` | 66 | | [MediaThumbnailSize](../../adminapi.json/components/schemas/MediaThumbnailSize) | `/api/media-thumbnail-size` | 67 | | [MessageQueueStats](../../adminapi.json/components/schemas/MessageQueueStats) | `/api/message-queue-stats` | 68 | | [NewsletterRecipient](../../adminapi.json/components/schemas/NewsletterRecipient) | `/api/newsletter-recipient` | 69 | | [NewsletterRecipientTag](../../adminapi.json/components/schemas/NewsletterRecipientTag) | `/api/newsletter-recipient-tag` | 70 | | [NumberRange](../../adminapi.json/components/schemas/NumberRange) | `/api/number-range` | 71 | | [NumberRangeSalesChannel](../../adminapi.json/components/schemas/NumberRangeSalesChannel) | `/api/number-range-sales-channel` | 72 | | [NumberRangeState](../../adminapi.json/components/schemas/NumberRangeState) | `/api/number-range-state` | 73 | | [NumberRangeType](../../adminapi.json/components/schemas/NumberRangeType) | `/api/number-range-type` | 74 | | [Order](../../adminapi.json/components/schemas/Order) | `/api/order` | 75 | | [OrderAddress](../../adminapi.json/components/schemas/OrderAddress) | `/api/order-address` | 76 | | [OrderCustomer](../../adminapi.json/components/schemas/OrderCustomer) | `/api/order-customer` | 77 | | [OrderDelivery](../../adminapi.json/components/schemas/OrderDelivery) | `/api/order-delivery` | 78 | | [OrderDeliveryPosition](../../adminapi.json/components/schemas/OrderDeliveryPosition) | `/api/order-delivery-position` | 79 | | [OrderLineItem](../../adminapi.json/components/schemas/OrderLineItem) | `/api/order-line-item` | 80 | | [OrderTag](../../adminapi.json/components/schemas/OrderTag) | `/api/order-tag` | 81 | | [OrderTransaction](../../adminapi.json/components/schemas/OrderTransaction) | `/api/order-transaction` | 82 | | [PaymentMethod](../../adminapi.json/components/schemas/PaymentMethod) | `/api/payment-method` | 83 | | [Plugin](../../adminapi.json/components/schemas/Plugin) | `/api/plugin` | 84 | | [Product](../../adminapi.json/components/schemas/Product) | `/api/product` | 85 | | [ProductCategory](../../adminapi.json/components/schemas/ProductCategory) | `/api/product-category` | 86 | | [ProductCategoryTree](../../adminapi.json/components/schemas/ProductCategoryTree) | `/api/product-category-tree` | 87 | | [ProductConfiguratorSetting](../../adminapi.json/components/schemas/ProductConfiguratorSetting) | `/api/product-configurator-setting` | 88 | | [ProductCrossSelling](../../adminapi.json/components/schemas/ProductCrossSelling) | `/api/product-cross-selling` | 89 | | [ProductCrossSellingAssignedProducts](../../adminapi.json/components/schemas/ProductCrossSellingAssignedProducts) | `/api/product-cross-selling-assigned-products` | 90 | | [ProductCustomFieldSet](../../adminapi.json/components/schemas/ProductCustomFieldSet) | `/api/product-custom-field-set` | 91 | | [ProductExport](../../adminapi.json/components/schemas/ProductExport) | `/api/product-export` | 92 | | [ProductFeatureSet](../../adminapi.json/components/schemas/ProductFeatureSet) | `/api/product-feature-set` | 93 | | [ProductKeywordDictionary](../../adminapi.json/components/schemas/ProductKeywordDictionary) | `/api/product-keyword-dictionary` | 94 | | [ProductManufacturer](../../adminapi.json/components/schemas/ProductManufacturer) | `/api/product-manufacturer` | 95 | | [ProductMedia](../../adminapi.json/components/schemas/ProductMedia) | `/api/product-media` | 96 | | [ProductOption](../../adminapi.json/components/schemas/ProductOption) | `/api/product-option` | 97 | | [ProductPrice](../../adminapi.json/components/schemas/ProductPrice) | `/api/product-price` | 98 | | [ProductProperty](../../adminapi.json/components/schemas/ProductProperty) | `/api/product-property` | 99 | | [ProductReview](../../adminapi.json/components/schemas/ProductReview) | `/api/product-review` | 100 | | [ProductSearchConfig](../../adminapi.json/components/schemas/ProductSearchConfig) | `/api/product-search-config` | 101 | | [ProductSearchConfigField](../../adminapi.json/components/schemas/ProductSearchConfigField) | `/api/product-search-config-field` | 102 | | [ProductSearchKeyword](../../adminapi.json/components/schemas/ProductSearchKeyword) | `/api/product-search-keyword` | 103 | | [ProductSorting](../../adminapi.json/components/schemas/ProductSorting) | `/api/product-sorting` | 104 | | [ProductStream](../../adminapi.json/components/schemas/ProductStream) | `/api/product-stream` | 105 | | [ProductStreamFilter](../../adminapi.json/components/schemas/ProductStreamFilter) | `/api/product-stream-filter` | 106 | | [ProductStreamMapping](../../adminapi.json/components/schemas/ProductStreamMapping) | `/api/product-stream-mapping` | 107 | | [ProductTag](../../adminapi.json/components/schemas/ProductTag) | `/api/product-tag` | 108 | | [ProductVisibility](../../adminapi.json/components/schemas/ProductVisibility) | `/api/product-visibility` | 109 | | [Promotion](../../adminapi.json/components/schemas/Promotion) | `/api/promotion` | 110 | | [PromotionCartRule](../../adminapi.json/components/schemas/PromotionCartRule) | `/api/promotion-cart-rule` | 111 | | [PromotionDiscount](../../adminapi.json/components/schemas/PromotionDiscount) | `/api/promotion-discount` | 112 | | [PromotionDiscountPrices](../../adminapi.json/components/schemas/PromotionDiscountPrices) | `/api/promotion-discount-prices` | 113 | | [PromotionDiscountRule](../../adminapi.json/components/schemas/PromotionDiscountRule) | `/api/promotion-discount-rule` | 114 | | [PromotionIndividualCode](../../adminapi.json/components/schemas/PromotionIndividualCode) | `/api/promotion-individual-code` | 115 | | [PromotionOrderRule](../../adminapi.json/components/schemas/PromotionOrderRule) | `/api/promotion-order-rule` | 116 | | [PromotionPersonaCustomer](../../adminapi.json/components/schemas/PromotionPersonaCustomer) | `/api/promotion-persona-customer` | 117 | | [PromotionPersonaRule](../../adminapi.json/components/schemas/PromotionPersonaRule) | `/api/promotion-persona-rule` | 118 | | [PromotionSalesChannel](../../adminapi.json/components/schemas/PromotionSalesChannel) | `/api/promotion-sales-channel` | 119 | | [PromotionSetgroup](../../adminapi.json/components/schemas/PromotionSetgroup) | `/api/promotion-setgroup` | 120 | | [PromotionSetgroupRule](../../adminapi.json/components/schemas/PromotionSetgroupRule) | `/api/promotion-setgroup-rule` | 121 | | [PropertyGroup](../../adminapi.json/components/schemas/PropertyGroup) | `/api/property-group` | 122 | | [PropertyGroupOption](../../adminapi.json/components/schemas/PropertyGroupOption) | `/api/property-group-option` | 123 | | [Rule](../../adminapi.json/components/schemas/Rule) | `/api/rule` | 124 | | [RuleCondition](../../adminapi.json/components/schemas/RuleCondition) | `/api/rule-condition` | 125 | | [SalesChannel](../../adminapi.json/components/schemas/SalesChannel) | `/api/sales-channel` | 126 | | [SalesChannelAnalytics](../../adminapi.json/components/schemas/SalesChannelAnalytics) | `/api/sales-channel-analytics` | 127 | | [SalesChannelCountry](../../adminapi.json/components/schemas/SalesChannelCountry) | `/api/sales-channel-country` | 128 | | [SalesChannelCurrency](../../adminapi.json/components/schemas/SalesChannelCurrency) | `/api/sales-channel-currency` | 129 | | [SalesChannelDomain](../../adminapi.json/components/schemas/SalesChannelDomain) | `/api/sales-channel-domain` | 130 | | [SalesChannelLanguage](../../adminapi.json/components/schemas/SalesChannelLanguage) | `/api/sales-channel-language` | 131 | | [SalesChannelPaymentMethod](../../adminapi.json/components/schemas/SalesChannelPaymentMethod) | `/api/sales-channel-payment-method` | 132 | | [SalesChannelShippingMethod](../../adminapi.json/components/schemas/SalesChannelShippingMethod) | `/api/sales-channel-shipping-method` | 133 | | [SalesChannelType](../../adminapi.json/components/schemas/SalesChannelType) | `/api/sales-channel-type` | 134 | | [Salutation](../../adminapi.json/components/schemas/Salutation) | `/api/salutation` | 135 | | [ScheduledTask](../../adminapi.json/components/schemas/ScheduledTask) | `/api/scheduled-task` | 136 | | [SeoUrl](../../adminapi.json/components/schemas/SeoUrl) | `/api/seo-url` | 137 | | [SeoUrlTemplate](../../adminapi.json/components/schemas/SeoUrlTemplate) | `/api/seo-url-template` | 138 | | [ShippingMethod](../../adminapi.json/components/schemas/ShippingMethod) | `/api/shipping-method` | 139 | | [ShippingMethodPrice](../../adminapi.json/components/schemas/ShippingMethodPrice) | `/api/shipping-method-price` | 140 | | [ShippingMethodTag](../../adminapi.json/components/schemas/ShippingMethodTag) | `/api/shipping-method-tag` | 141 | | [Snippet](../../adminapi.json/components/schemas/Snippet) | `/api/snippet` | 142 | | [SnippetSet](../../adminapi.json/components/schemas/SnippetSet) | `/api/snippet-set` | 143 | | [StateMachine](../../adminapi.json/components/schemas/StateMachine) | `/api/state-machine` | 144 | | [StateMachineHistory](../../adminapi.json/components/schemas/StateMachineHistory) | `/api/state-machine-history` | 145 | | [StateMachineState](../../adminapi.json/components/schemas/StateMachineState) | `/api/state-machine-state` | 146 | | [StateMachineTransition](../../adminapi.json/components/schemas/StateMachineTransition) | `/api/state-machine-transition` | 147 | | [SystemConfig](../../adminapi.json/components/schemas/SystemConfig) | `/api/system-config` | 148 | | [Tag](../../adminapi.json/components/schemas/Tag) | `/api/tag` | 149 | | [Tax](../../adminapi.json/components/schemas/Tax) | `/api/tax` | 150 | | [TaxRule](../../adminapi.json/components/schemas/TaxRule) | `/api/tax-rule` | 151 | | [TaxRuleType](../../adminapi.json/components/schemas/TaxRuleType) | `/api/tax-rule-type` | 152 | | [Theme](../../adminapi.json/components/schemas/Theme) | `/api/theme` | 153 | | [ThemeMedia](../../adminapi.json/components/schemas/ThemeMedia) | `/api/theme-media` | 154 | | [ThemeSalesChannel](../../adminapi.json/components/schemas/ThemeSalesChannel) | `/api/theme-sales-channel` | 155 | | [Unit](../../adminapi.json/components/schemas/Unit) | `/api/unit` | 156 | | [User](../../adminapi.json/components/schemas/User) | `/api/user` | 157 | | [UserAccessKey](../../adminapi.json/components/schemas/UserAccessKey) | `/api/user-access-key` | 158 | | [UserConfig](../../adminapi.json/components/schemas/UserConfig) | `/api/user-config` | 159 | | [UserRecovery](../../adminapi.json/components/schemas/UserRecovery) | `/api/user-recovery` | 160 | | [Webhook](../../adminapi.json/components/schemas/Webhook) | `/api/webhook` | 161 | | [WebhookEventLog](../../adminapi.json/components/schemas/WebhookEventLog) | `/api/webhook-event-log` | -------------------------------------------------------------------------------- /docs/guides/quick-start/02-product-management.md: -------------------------------------------------------------------------------- 1 | --- 2 | stoplight-id: e51cf55ab14a4 3 | --- 4 | 5 | # Product Management 6 | 7 | This section explains the handling of the product data structure. 8 | 9 | To start easy, below is a sample request to create a product with simple data from its complex API schema. 10 | 11 | ## Create a new product with a simple payload 12 | 13 | A product has only a handful of required fields: 14 | 15 | * name [string] 16 | * productNumber [string] 17 | * taxId [string] 18 | * price [object] 19 | * stock [int] 20 | 21 | The smallest required payload for a product can therefore be as follows: 22 | 23 | ```sample http 24 | { 25 | "method": "post", 26 | "url": "http://localhost/api/product", 27 | "headers": { 28 | "Content-Type": "application/json", 29 | "Accept": "application/json", 30 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 31 | }, 32 | "body": { 33 | "name": "test", 34 | "productNumber": "random", 35 | "stock": 10, 36 | "taxId": "a5da76b447db4d0aba62e6512dadf45b", 37 | "price": [ 38 | { 39 | "currencyId" : "b7d2554b0ce847cd82f3ac9bd1c0dfca", 40 | "gross": 15, 41 | "net": 10, 42 | "linked" : false 43 | } 44 | ] 45 | } 46 | } 47 | } 48 | ``` 49 | 50 | ```description json_schema 51 | { 52 | "type": "object", 53 | "title": "MinimalProductPayload", 54 | "description": "Parameters for product creation.", 55 | "properties": { 56 | "name": { 57 | "description": "Name of the product.", 58 | "type": "string" 59 | }, 60 | "productNumber": { 61 | "description": "Any random number given to product.", 62 | "type": "string" 63 | }, 64 | "stock": { 65 | "description": "Availability of stock.", 66 | "type": "string" 67 | }, 68 | "taxId": { 69 | "description": "ID of [tax](../../../adminapi.json/components/schemas/Tax)", 70 | "type": "string" 71 | }, 72 | "price": [] 73 | "currencyId": { 74 | "description": "ID of [currency](../../../adminapi.json/components/schemas/Currency).", 75 | "type": "string" 76 | }, 77 | "gross": { 78 | "description": "Gross price of a product.", 79 | "type": "string" 80 | }, 81 | "net": { 82 | "description": "Net price of a product.", 83 | "type": "string" 84 | }, 85 | "linked": { 86 | "description": "If set to true, net price is automatically calculated based on gross price and stored tax rate.", 87 | "type": "boolean" 88 | } 89 | } 90 | } 91 | ``` 92 | 93 | The following payload examples contain UUIDs for various entities such as currencies, tax rates, manufacturers, or properties. These IDs are different on each system and must be adjusted accordingly. 94 | 95 | ## Category 96 | 97 | Products are organized into categories within the catalog. 98 | 99 | Below is a sample request to create a category: 100 | 101 | ```sample http 102 | { 103 | "method": "post", 104 | "url": "http://localhost/api/category", 105 | "headers": { 106 | "Content-Type": "application/json", 107 | "Accept": "application/json", 108 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 109 | }, 110 | "body": { 111 | "displayNestedProducts": true, 112 | "type": "page", 113 | "productAssignmentType": "product", 114 | "name": "Home" 115 | } 116 | } 117 | ``` 118 | 119 | ```description json_schema 120 | { 121 | "type": "object", 122 | "description": "Parameters for category creation.", 123 | "properties": { 124 | "displayNestedProducts": { 125 | "description": "Specify `true` to display nested products else `false`.", 126 | "type": "boolean" 127 | }, 128 | "type": { 129 | "description": "Types of category - `folder`, `link`, `page` ", 130 | "type": "string", 131 | "Example": " `product`, `category` " 132 | }, 133 | "productAssignmentType": { 134 | "description": "Accepts values `product`, and `product-stream` for products added explicitly and added via Dynamic product group, respectively.", 135 | "type": "string" 136 | }, 137 | "name": { 138 | "description": "Name of the category", 139 | "type": "string" 140 | } 141 | } 142 | } 143 | ``` 144 | 145 | ## Product assignment 146 | 147 | Every product must be assigned to a category for its display. It can be explicitly set or can be assigned as a [dynamic product group](../../../adminapi.json/components/schemas/ProductStream) to a category. 148 | 149 | Let us assign the test product to the *Home* category created earlier: 150 | 151 | ```sample http 152 | { 153 | "method": "PATCH", 154 | "url": "http://localhost/api/category/a11d11c732d54debad6da3b38ad07b11", 155 | "headers": { 156 | "Content-Type": "application/json", 157 | "Accept": "application/json", 158 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 159 | }, 160 | "body": { 161 | "productAssignmentType": "product_stream", 162 | "productStreamId": "bca25935854b4a0181681c81bcacd7ba" 163 | } 164 | } 165 | ``` 166 | 167 | ```description json_schema 168 | { 169 | "type": "object", 170 | "description": "Parameters for product assignment.", 171 | "properties": { 172 | "id": { 173 | "description": "Unique ID of category.", 174 | "type": "string" 175 | }, 176 | "productAssignmentType": { 177 | "description": "Accepts values `product`, and `product-stream` for products added explicitly and added via Dynamic product group, respectively.", 178 | "type": "string" 179 | }, 180 | "productStreamId": { 181 | "description": "Unique ID Dynamic product group.", 182 | "type": "string" 183 | } 184 | } 185 | } 186 | ``` 187 | 188 | ### Assigning of properties and categories 189 | 190 | The product has various `many-to-many` associations. This type of association is a link between the records. Examples are the `properties` and `categories` of a product. 191 | 192 | For assigning several `properties` and `categories`, this is an exemplary payload: 193 | 194 | ```javascript 195 | { 196 | "name": "test", 197 | "productNumber": "random", 198 | "stock": 10, 199 | "taxId": "db6f3ed762d14b0395a3fd2dc460db42", 200 | "properties": [ 201 | { "id": "b6dd111fff0f4e3abebb88d02fe2021e"}, 202 | { "id": "b9f4908785ef4902b8d9e64260f565ae"} 203 | ], 204 | "categories": [ 205 | { "id": "b7d2554b0ce847cd82f3ac9bd1c0dfca" }, 206 | { "id": "cdea94b4f9452254a20b91ec1cd538b9" } 207 | ] 208 | } 209 | ``` 210 | 211 | To remove these `properties` and `categories`, the corresponding routes can be used for the mapping entities: 212 | 213 | * `DELETE /api/product/{productId}/properties/{optionId}` 214 | * `DELETE /api/product/{productId}/categories/{categoryId}` 215 | 216 | To delete several assignments at once, the `/_action/sync` (see also [Bulk payloads](../concepts/endpoint-structure/writing-entities/bulk-payloads.md)) route can be used: 217 | 218 | ```javascript 219 | { 220 | // This key can be defined individually 221 | "unassign-categories": { 222 | "entity": "product_category", 223 | "action": "delete", 224 | "payload": [ 225 | { "productId": "069d109b9b484f9d992ec5f478f9c2a1", "categoryId": "1f3cf89039e44e67aa74cccd90efb905" }, 226 | { "productId": "073db754b4d14ecdb3aa6cefa2ba98a7", "categoryId": "a6d1212c774546db9b54f05d355376c1" } 227 | ] 228 | }, 229 | 230 | // This key can be defined individually 231 | "unassign-properties": { 232 | "entity": "product_property", 233 | "action": "delete", 234 | "payload": [ 235 | { "productId": "069d109b9b484f9d992ec5f478f9c2a1", "optionId": "2d858284d5864fe68de046affadb1fc3" }, 236 | { "productId": "069d109b9b484f9d992ec5f478f9c2a1", "optionId": "17eb3eb8f77f4d87835abb355e41758e" }, 237 | { "productId": "073db754b4d14ecdb3aa6cefa2ba98a7", "optionId": "297b6bd763c94210b5f8ee5e700fadde" } 238 | ] 239 | } 240 | } 241 | ``` 242 | 243 | ### `CategoriesRo` Association 244 | 245 | The `product.categories` association contains the assignment of products and their categories. This table is not queried in the storefront because all products of subcategories should be displayed in listings as well. Therefore there is another association: `product.categoriesRo`. This association is read-only and is filled automatically by the system. This table contains all assigned categories of the product as well as all parent categories. 246 | 247 | ## Product reviews 248 | 249 | Reviews are comments that stand as a means to evaluate products by customers. The below API request adds a product review to a particular product: 250 | 251 | ```sample http 252 | { 253 | "method": "post", 254 | "url": "http://localhost/api/product-review", 255 | "headers": { 256 | "Content-Type": "application/json", 257 | "Accept": "application/json", 258 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 259 | }, 260 | "body": { 261 | "productId": "a55ca50a2cef46d5b11a12c4b4614988", 262 | "salesChannelId": "98432def39fc4624b33213a56b8c944d", 263 | "languageId": "2fbb5fe2e29a4d70aa5854ce7ce3e20b", 264 | "title": "Ice Cream Scoop", 265 | "content": "Very Good" 266 | } 267 | } 268 | ``` 269 | 270 | ```description json_schema 271 | { 272 | "type": "object", 273 | "description": "Parameters for product reviews.", 274 | "properties": { 275 | "productId": { 276 | "description": "Unique ID of a product.", 277 | "type": "string" 278 | }, 279 | "salesChannelId": { 280 | "description": " Unique ID of defined sales channel.", 281 | "type": "string", 282 | }, 283 | "languageId": { 284 | "description": "Unique ID of language.", 285 | "type": "string" 286 | }, 287 | "title": { 288 | "description": "Caption for the review.", 289 | "type": "string" 290 | }, 291 | "content": { 292 | "description": "Review description.", 293 | "type": "string" 294 | } 295 | } 296 | } 297 | ``` 298 | 299 | ## Cross-selling 300 | 301 | Cross-selling adds product recommendations and interesting content to achieve an optimal shopping experience in the shop. 302 | 303 | ```sample http 304 | { 305 | "method": "post", 306 | "url": "http://localhost/api/product/a55ca50a2cef46d5b11a12c4b4614988/cross-sellings", 307 | "headers": { 308 | "Content-Type": "application/json", 309 | "Accept": "application/json", 310 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 311 | }, 312 | "body": { 313 | "name": "sample_review", 314 | "type": "productStream", 315 | "position": 1, 316 | "sortBy": "name", 317 | "sortDirection": "ASC", 318 | "active": true, 319 | "limit": 24, 320 | "productId": "bca25935854b4a0181681c81bcacd7ba" 321 | } 322 | } 323 | ``` 324 | 325 | ```description json_schema 326 | { 327 | "type": "object", 328 | "description": "Parameters for product reviews.", 329 | "properties": { 330 | "name": { 331 | "description": "Name of the cross-selling.", 332 | "type": "string" 333 | }, 334 | "type": { 335 | "description": "Accepts `productList` or `productStream` type.", 336 | "type": "string" 337 | }, 338 | "position": { 339 | "description": "Position of the product to be displayed in the list. It accepts values greater than 1. When only one product list is to be displayed, the default position taken is 1.", 340 | "type": "integer", 341 | }, 342 | "sortBy": { 343 | "description": "Sort criteria by `name`, `price`.", 344 | "type": "string" 345 | }, 346 | "sortDirection": { 347 | "description": "Sorting can be `ASC` or `DESC`.", 348 | "type": "string" 349 | }, 350 | "active": { 351 | "description": "When active is `true`, product recommendation is visible.", 352 | "type": "boolean" 353 | }, 354 | "limit": { 355 | "description": "Maximum number of products displayed in a row.", 356 | "type": "string" 357 | }, 358 | "productId": { 359 | "description": "Unique ID of product.", 360 | "type": "string" 361 | } 362 | } 363 | } 364 | ``` 365 | 366 | ## Price 367 | 368 | A particular product's price can be fetched, updated, or a [price rule can be created](#quantity-and-rule-price-structure). 369 | 370 | Price handling is one of the edge cases in the product data structure. There are three different prices for a product, which can be queried via API: 371 | 372 | * `product.price` 373 | * `product.prices` 374 | * `product.listingPrices` 375 | 376 | Only the first two can be written via API \(`product.price`, `product.prices`\). The `product.price` is the "simple" price of a product. It does not contain quantity information, nor is it bound to any `rule`. 377 | 378 | To update the price for a particular product, use the below endpoint: 379 | 380 | ```text 381 | PATCH /api/product/{product-id} 382 | ``` 383 | 384 | ```sample http 385 | { 386 | "method": "patch", 387 | "url": "http://localhost/api/product/a55ca50a2cef46d5b11a12c4b4614988", 388 | "headers": { 389 | "Content-Type": "application/json", 390 | "Accept": "application/json", 391 | "Authorization": "Bearer YOUR_ACCESS_TOKEN" 392 | }, 393 | "body": { 394 | "price": [ 395 | { 396 | "currencyId": "b7d2554b0ce847cd82f3ac9bd1c0dfca", 397 | "net": 164, 398 | "gross": 180, 399 | "linked": false 400 | } 401 | ] 402 | } 403 | } 404 | ``` 405 | 406 | ```description json_schema 407 | { 408 | "type": "object", 409 | "description": "Parameters for price updation", 410 | "properties": { 411 | "price": [] 412 | "currencyId": { 413 | "description": "ID of the currency to which the price belongs.", 414 | "type": "string" 415 | }, 416 | "gross": { 417 | "description": "This price is displayed to customers who see gross prices in the shop.", 418 | "type": "string" 419 | }, 420 | "net": { 421 | "description": "This price is shown to customers who see net prices in the shop.", 422 | "type": "string" 423 | }, 424 | "linked": { 425 | "description": "If set to true, net price is automatically calculated based on gross price and stored tax rate.", 426 | "type": "boolean" 427 | } 428 | } 429 | } 430 | ``` 431 | 432 | ### Currency price structure 433 | 434 | Within the price, different currency prices are available. Each currency price includes properties `currencyId`, `gross`, `net`, `linked`. 435 | 436 | To define prices for a product in different currencies, this is an exemplary payload: 437 | 438 | ```javascript 439 | { 440 | "name": "test", 441 | "productNumber": "random", 442 | "stock": 10, 443 | "taxId": "db6f3ed762d14b0395a3fd2dc460db42", 444 | "price": [ 445 | { 446 | // euro price 447 | "currencyId" : "db6f3ed762d14b0395a3fd2dc460db42", 448 | "gross": 15, 449 | "net": 10, 450 | "linked" : false 451 | }, 452 | { 453 | // dollar price 454 | "currencyId" : "16a190bd85b741c08873cfeaeb0ad8e1", 455 | "gross": 120, 456 | "net": 100.84, 457 | "linked" : true 458 | }, 459 | { 460 | // pound price 461 | "currencyId" : "b7d2554b0ce847cd82f3ac9bd1c0dfca", 462 | "gross": 66, 463 | "net": 55.46, 464 | "linked" : true 465 | } 466 | ] 467 | } 468 | ``` 469 | 470 | ### Quantity and rule price structure 471 | 472 | As an extension to the `product.price`, there is `product.prices`. These are prices that are bound to a `rule`. Rules \(`rule` entity\) are prioritized. If there are several rules for a customer, the customer will see the rule price with the highest priority. In addition to the dependency on a rule, a quantity discount can be defined using these prices. 473 | 474 | Each price in `product.prices` has the following properties: 475 | 476 | * `quantityStart` \[int\] - Indicates the quantity from which this price applies. 477 | * `quantityEnd` \[int\|null\] - Specifies the quantity until this price is valid. 478 | * `ruleId` \[string\] - Id of the rule to which the price applies. 479 | * `price` \[object\[\]\] - Includes currency prices \(same structure as `product.price`\). 480 | 481 | To define prices for a rule including a quantity discount, this is an exemplary payload: 482 | 483 | ```javascript 484 | { 485 | "name": "test", 486 | "productNumber": "random", 487 | "stock": 10, 488 | "taxId": "db6f3ed762d14b0395a3fd2dc460db42", 489 | "price": [ 490 | { 491 | "currencyId": "b7d2554b0ce847cd82f3ac9bd1c0dfca", 492 | "gross": 15, 493 | "net": 10, 494 | "linked": false 495 | } 496 | ], 497 | "prices": [ 498 | { 499 | "id": "9fa35118fe7c4502947986849379d564", 500 | "quantityStart": 1, 501 | "quantityEnd": 10, 502 | "ruleId": "43be477b241448ecacd7ea2a266f8ec7", 503 | "price": [ 504 | { 505 | "currencyId": "b7d2554b0ce847cd82f3ac9bd1c0dfca", 506 | "gross": 20, 507 | "net": 16.81, 508 | "linked": true 509 | } 510 | ] 511 | 512 | }, 513 | { 514 | "id": "db6f3ed762d14b0395a3fd2dc460db42", 515 | "quantityStart": 11, 516 | "quantityEnd": null, 517 | "ruleId": "43be477b241448ecacd7ea2a266f8ec7", 518 | "price": [ 519 | { 520 | "currencyId": "b7d2554b0ce847cd82f3ac9bd1c0dfca", 521 | "gross": 19, 522 | "net": 15.97, 523 | "linked": true 524 | } 525 | ] 526 | } 527 | ] 528 | } 529 | ``` 530 | 531 | ### Listing price handling 532 | 533 | The third price property available on the product is the `product.listingPrices`. These prices are determined automatically by the system. The price range for the corresponding products is available here. Prices are determined based on all variants of prices that could be displayed to the customer in the shop. 534 | 535 | Each price within this object contains the following properties: 536 | 537 | * `currencyId` \[string\] - The currency to which this price applies. 538 | * `ruleId` \[string\] - The rule to which this price applies. 539 | * `from` \[price-obj\] - The lowest price possible for the product in this currency. 540 | * `to` \[price-obj\] - The highest price that is possible for the product in this currency. 541 | -------------------------------------------------------------------------------- /SwagCommercial-adminapi.summary.json: -------------------------------------------------------------------------------- 1 | { 2 | "paths": [ 3 | "/_action/create-employee", 4 | "/_action/custom-price", 5 | "/_action/invite-employee", 6 | "/_action/media/external-link", 7 | "/_action/media/upload", 8 | "/_action/media/upload_by_url", 9 | "/_action/quote/{quoteId}/comment", 10 | "/_action/quote/{quoteId}/lineItem", 11 | "/_action/quote/{quoteId}/product/{productId}", 12 | "/_action/quote/{quoteId}/recalculate", 13 | "/_action/share-config/download/{entity}/{id}", 14 | "/_action/share-config/upload/{entity}", 15 | "/_action/text-to-image/generate", 16 | "/_action/theme/{themeId}", 17 | "/_action/update-employee", 18 | "/_proxy-quote/{salesChannelId}", 19 | "/advanced-search-action", 20 | "/advanced-search-action-search-term", 21 | "/advanced-search-action-search-term/{id}", 22 | "/advanced-search-action/{id}", 23 | "/advanced-search-boosting", 24 | "/advanced-search-boosting/{id}", 25 | "/advanced-search-config", 26 | "/advanced-search-config-field", 27 | "/advanced-search-config-field/{id}", 28 | "/advanced-search-config/{id}", 29 | "/advanced-search-entity-stream", 30 | "/advanced-search-entity-stream-filter", 31 | "/advanced-search-entity-stream-filter/{id}", 32 | "/advanced-search-entity-stream/{id}", 33 | "/advanced-search-synonym", 34 | "/advanced-search-synonym/{id}", 35 | "/aggregate/advanced-search-action", 36 | "/aggregate/advanced-search-action-search-term", 37 | "/aggregate/advanced-search-boosting", 38 | "/aggregate/advanced-search-config", 39 | "/aggregate/advanced-search-config-field", 40 | "/aggregate/advanced-search-entity-stream", 41 | "/aggregate/advanced-search-entity-stream-filter", 42 | "/aggregate/advanced-search-synonym", 43 | "/aggregate/b2b-business-partner", 44 | "/aggregate/b2b-components-approval-rule", 45 | "/aggregate/b2b-components-approval-rule-app-script-condition", 46 | "/aggregate/b2b-components-organization", 47 | "/aggregate/b2b-components-organization-customer-address", 48 | "/aggregate/b2b-components-pending-order", 49 | "/aggregate/b2b-components-pending-order-address", 50 | "/aggregate/b2b-components-role", 51 | "/aggregate/b2b-components-shopping-list", 52 | "/aggregate/b2b-components-shopping-list-line-item", 53 | "/aggregate/b2b-employee", 54 | "/aggregate/b2b-order-employee", 55 | "/aggregate/b2b-permission", 56 | "/aggregate/custom-price", 57 | "/aggregate/customer-specific-features", 58 | "/aggregate/measurement-display-unit", 59 | "/aggregate/measurement-system", 60 | "/aggregate/media-ai-tag", 61 | "/aggregate/order-product-warehouse", 62 | "/aggregate/order-return", 63 | "/aggregate/order-return-line-item", 64 | "/aggregate/order-return-line-item-reason", 65 | "/aggregate/order-warehouse-group", 66 | "/aggregate/product-review-summary", 67 | "/aggregate/product-warehouse", 68 | "/aggregate/quote", 69 | "/aggregate/quote-comment", 70 | "/aggregate/quote-delivery", 71 | "/aggregate/quote-delivery-position", 72 | "/aggregate/quote-document", 73 | "/aggregate/quote-employee", 74 | "/aggregate/quote-line-item", 75 | "/aggregate/quote-transaction", 76 | "/aggregate/spatial-render-config-size", 77 | "/aggregate/spatial-scene", 78 | "/aggregate/spatial-scene-camera", 79 | "/aggregate/spatial-scene-group", 80 | "/aggregate/spatial-scene-light", 81 | "/aggregate/spatial-scene-material", 82 | "/aggregate/spatial-scene-object", 83 | "/aggregate/spatial-scene-primitive", 84 | "/aggregate/sso-provider", 85 | "/aggregate/sso-provider-customer", 86 | "/aggregate/subscription", 87 | "/aggregate/subscription-address", 88 | "/aggregate/subscription-customer", 89 | "/aggregate/subscription-interval", 90 | "/aggregate/subscription-plan", 91 | "/aggregate/swag-delay-action", 92 | "/aggregate/warehouse", 93 | "/aggregate/warehouse-group", 94 | "/api/_admin/rule-builder-preview/{orderId}", 95 | "/app-system/privileges/requested", 96 | "/app-system/{appName}/privileges", 97 | "/app-system/{appName}/privileges/accepted", 98 | "/b2b-business-partner", 99 | "/b2b-business-partner/{id}", 100 | "/b2b-components-approval-rule", 101 | "/b2b-components-approval-rule-app-script-condition", 102 | "/b2b-components-approval-rule-app-script-condition/{id}", 103 | "/b2b-components-approval-rule/{id}", 104 | "/b2b-components-organization", 105 | "/b2b-components-organization-customer-address", 106 | "/b2b-components-organization-customer-address/{id}", 107 | "/b2b-components-organization/{id}", 108 | "/b2b-components-pending-order", 109 | "/b2b-components-pending-order-address", 110 | "/b2b-components-pending-order-address/{id}", 111 | "/b2b-components-pending-order/{id}", 112 | "/b2b-components-role", 113 | "/b2b-components-role/{id}", 114 | "/b2b-components-shopping-list", 115 | "/b2b-components-shopping-list-line-item", 116 | "/b2b-components-shopping-list-line-item/{id}", 117 | "/b2b-components-shopping-list/{id}", 118 | "/b2b-employee", 119 | "/b2b-employee/{id}", 120 | "/b2b-order-employee", 121 | "/b2b-order-employee/{id}", 122 | "/b2b-permission", 123 | "/b2b-permission/{id}", 124 | "/custom-price", 125 | "/custom-price/{id}", 126 | "/customer-specific-features", 127 | "/customer-specific-features/{id}", 128 | "/measurement-display-unit", 129 | "/measurement-display-unit/{id}", 130 | "/measurement-system", 131 | "/measurement-system/{id}", 132 | "/media-ai-tag", 133 | "/media-ai-tag/{id}", 134 | "/order-product-warehouse", 135 | "/order-product-warehouse/{id}", 136 | "/order-return", 137 | "/order-return-line-item", 138 | "/order-return-line-item-reason", 139 | "/order-return-line-item-reason/{id}", 140 | "/order-return-line-item/{id}", 141 | "/order-return/{id}", 142 | "/order-warehouse-group", 143 | "/order-warehouse-group/{id}", 144 | "/product-review-summary", 145 | "/product-review-summary/{id}", 146 | "/product-warehouse", 147 | "/product-warehouse/{id}", 148 | "/quote", 149 | "/quote-comment", 150 | "/quote-comment/{id}", 151 | "/quote-delivery", 152 | "/quote-delivery-position", 153 | "/quote-delivery-position/{id}", 154 | "/quote-delivery/{id}", 155 | "/quote-document", 156 | "/quote-document/{id}", 157 | "/quote-employee", 158 | "/quote-employee/{id}", 159 | "/quote-line-item", 160 | "/quote-line-item/{id}", 161 | "/quote-transaction", 162 | "/quote-transaction/{id}", 163 | "/quote/{id}", 164 | "/search/advanced-search-action", 165 | "/search/advanced-search-action-search-term", 166 | "/search/advanced-search-boosting", 167 | "/search/advanced-search-config", 168 | "/search/advanced-search-config-field", 169 | "/search/advanced-search-entity-stream", 170 | "/search/advanced-search-entity-stream-filter", 171 | "/search/advanced-search-synonym", 172 | "/search/b2b-business-partner", 173 | "/search/b2b-components-approval-rule", 174 | "/search/b2b-components-approval-rule-app-script-condition", 175 | "/search/b2b-components-organization", 176 | "/search/b2b-components-organization-customer-address", 177 | "/search/b2b-components-pending-order", 178 | "/search/b2b-components-pending-order-address", 179 | "/search/b2b-components-role", 180 | "/search/b2b-components-shopping-list", 181 | "/search/b2b-components-shopping-list-line-item", 182 | "/search/b2b-employee", 183 | "/search/b2b-order-employee", 184 | "/search/b2b-permission", 185 | "/search/custom-price", 186 | "/search/customer-specific-features", 187 | "/search/measurement-display-unit", 188 | "/search/measurement-system", 189 | "/search/media-ai-tag", 190 | "/search/order-product-warehouse", 191 | "/search/order-return", 192 | "/search/order-return-line-item", 193 | "/search/order-return-line-item-reason", 194 | "/search/order-warehouse-group", 195 | "/search/product-review-summary", 196 | "/search/product-warehouse", 197 | "/search/quote", 198 | "/search/quote-comment", 199 | "/search/quote-delivery", 200 | "/search/quote-delivery-position", 201 | "/search/quote-document", 202 | "/search/quote-employee", 203 | "/search/quote-line-item", 204 | "/search/quote-transaction", 205 | "/search/spatial-render-config-size", 206 | "/search/spatial-scene", 207 | "/search/spatial-scene-camera", 208 | "/search/spatial-scene-group", 209 | "/search/spatial-scene-light", 210 | "/search/spatial-scene-material", 211 | "/search/spatial-scene-object", 212 | "/search/spatial-scene-primitive", 213 | "/search/sso-provider", 214 | "/search/sso-provider-customer", 215 | "/search/subscription", 216 | "/search/subscription-address", 217 | "/search/subscription-customer", 218 | "/search/subscription-interval", 219 | "/search/subscription-plan", 220 | "/search/swag-delay-action", 221 | "/search/warehouse", 222 | "/search/warehouse-group", 223 | "/spatial-render-config-size", 224 | "/spatial-render-config-size/{id}", 225 | "/spatial-scene", 226 | "/spatial-scene-camera", 227 | "/spatial-scene-camera/{id}", 228 | "/spatial-scene-group", 229 | "/spatial-scene-group/{id}", 230 | "/spatial-scene-light", 231 | "/spatial-scene-light/{id}", 232 | "/spatial-scene-material", 233 | "/spatial-scene-material/{id}", 234 | "/spatial-scene-object", 235 | "/spatial-scene-object/{id}", 236 | "/spatial-scene-primitive", 237 | "/spatial-scene-primitive/{id}", 238 | "/spatial-scene/{id}", 239 | "/sso-provider", 240 | "/sso-provider-customer", 241 | "/sso-provider-customer/{id}", 242 | "/sso-provider/{id}", 243 | "/subscription", 244 | "/subscription-address", 245 | "/subscription-address/{id}", 246 | "/subscription-customer", 247 | "/subscription-customer/{id}", 248 | "/subscription-interval", 249 | "/subscription-interval/{id}", 250 | "/subscription-plan", 251 | "/subscription-plan/{id}", 252 | "/subscription/{id}", 253 | "/swag-delay-action", 254 | "/swag-delay-action/{id}", 255 | "/warehouse", 256 | "/warehouse-group", 257 | "/warehouse-group/{id}", 258 | "/warehouse/{id}" 259 | ], 260 | "schemas": [ 261 | "AclRole", 262 | "AclRoleJsonApi", 263 | "AclUserRole", 264 | "AdvancedSearchAction", 265 | "AdvancedSearchActionJsonApi", 266 | "AdvancedSearchActionSearchTerm", 267 | "AdvancedSearchActionSearchTermJsonApi", 268 | "AdvancedSearchBoosting", 269 | "AdvancedSearchBoostingJsonApi", 270 | "AdvancedSearchConfig", 271 | "AdvancedSearchConfigField", 272 | "AdvancedSearchConfigFieldJsonApi", 273 | "AdvancedSearchConfigJsonApi", 274 | "AdvancedSearchEntityStream", 275 | "AdvancedSearchEntityStreamFilter", 276 | "AdvancedSearchEntityStreamFilterJsonApi", 277 | "AdvancedSearchEntityStreamJsonApi", 278 | "AdvancedSearchSynonym", 279 | "AdvancedSearchSynonymJsonApi", 280 | "Aggregation", 281 | "AggregationEntity", 282 | "AggregationFilter", 283 | "AggregationHistogram", 284 | "AggregationMetrics", 285 | "AggregationRange", 286 | "AggregationTerms", 287 | "App", 288 | "AppActionButton", 289 | "AppActionButtonJsonApi", 290 | "AppAdministrationSnippet", 291 | "AppAdministrationSnippetJsonApi", 292 | "AppCmsBlock", 293 | "AppCmsBlockJsonApi", 294 | "AppFlowAction", 295 | "AppFlowActionJsonApi", 296 | "AppFlowEvent", 297 | "AppFlowEventJsonApi", 298 | "AppJsonApi", 299 | "AppPaymentMethod", 300 | "AppPaymentMethodJsonApi", 301 | "AppScriptCondition", 302 | "AppScriptConditionJsonApi", 303 | "AppShippingMethod", 304 | "AppShippingMethodJsonApi", 305 | "AppTemplate", 306 | "AppTemplateJsonApi", 307 | "Associations", 308 | "B2bBusinessPartner", 309 | "B2bBusinessPartnerJsonApi", 310 | "B2bComponentsApprovalRule", 311 | "B2bComponentsApprovalRuleAppScriptCondition", 312 | "B2bComponentsApprovalRuleAppScriptConditionJsonApi", 313 | "B2bComponentsApprovalRuleJsonApi", 314 | "B2bComponentsOrganization", 315 | "B2bComponentsOrganizationCustomerAddress", 316 | "B2bComponentsOrganizationCustomerAddressJsonApi", 317 | "B2bComponentsOrganizationJsonApi", 318 | "B2bComponentsOrganizationPaymentMethod", 319 | "B2bComponentsOrganizationShippingMethod", 320 | "B2bComponentsPendingOrder", 321 | "B2bComponentsPendingOrderAddress", 322 | "B2bComponentsPendingOrderAddressJsonApi", 323 | "B2bComponentsPendingOrderJsonApi", 324 | "B2bComponentsRole", 325 | "B2bComponentsRoleJsonApi", 326 | "B2bComponentsShoppingList", 327 | "B2bComponentsShoppingListJsonApi", 328 | "B2bComponentsShoppingListLineItem", 329 | "B2bComponentsShoppingListLineItemJsonApi", 330 | "B2bEmployee", 331 | "B2bEmployeeJsonApi", 332 | "B2bOrderEmployee", 333 | "B2bOrderEmployeeJsonApi", 334 | "B2bPermission", 335 | "B2bPermissionJsonApi", 336 | "Category", 337 | "CategoryJsonApi", 338 | "CategoryTag", 339 | "CmsBlock", 340 | "CmsBlockJsonApi", 341 | "CmsPage", 342 | "CmsPageJsonApi", 343 | "CmsSection", 344 | "CmsSectionJsonApi", 345 | "CmsSlot", 346 | "CmsSlotJsonApi", 347 | "Country", 348 | "CountryJsonApi", 349 | "CountryState", 350 | "CountryStateJsonApi", 351 | "Criteria", 352 | "Currency", 353 | "CurrencyCountryRounding", 354 | "CurrencyCountryRoundingJsonApi", 355 | "CurrencyJsonApi", 356 | "CustomEntity", 357 | "CustomEntityJsonApi", 358 | "CustomField", 359 | "CustomFieldJsonApi", 360 | "CustomFieldSet", 361 | "CustomFieldSetJsonApi", 362 | "CustomFieldSetRelation", 363 | "CustomFieldSetRelationJsonApi", 364 | "CustomPrice", 365 | "CustomPriceJsonApi", 366 | "CustomPricingDeleteOperation", 367 | "CustomPricingPrice", 368 | "CustomPricingResponse", 369 | "CustomPricingUpsertOperation", 370 | "Customer", 371 | "CustomerAddress", 372 | "CustomerAddressJsonApi", 373 | "CustomerGroup", 374 | "CustomerGroupJsonApi", 375 | "CustomerGroupRegistrationSalesChannels", 376 | "CustomerJsonApi", 377 | "CustomerRecovery", 378 | "CustomerRecoveryJsonApi", 379 | "CustomerSpecificFeatures", 380 | "CustomerSpecificFeaturesJsonApi", 381 | "CustomerTag", 382 | "CustomerWishlist", 383 | "CustomerWishlistJsonApi", 384 | "CustomerWishlistProduct", 385 | "CustomerWishlistProductJsonApi", 386 | "DeliveryTime", 387 | "DeliveryTimeJsonApi", 388 | "Document", 389 | "DocumentBaseConfig", 390 | "DocumentBaseConfigJsonApi", 391 | "DocumentBaseConfigSalesChannel", 392 | "DocumentBaseConfigSalesChannelJsonApi", 393 | "DocumentJsonApi", 394 | "DocumentType", 395 | "DocumentTypeJsonApi", 396 | "EqualsFilter", 397 | "Filters", 398 | "Flow", 399 | "FlowJsonApi", 400 | "FlowSequence", 401 | "FlowSequenceJsonApi", 402 | "FlowTemplate", 403 | "FlowTemplateJsonApi", 404 | "ImportExportFile", 405 | "ImportExportFileJsonApi", 406 | "ImportExportLog", 407 | "ImportExportLogJsonApi", 408 | "ImportExportProfile", 409 | "ImportExportProfileJsonApi", 410 | "Includes", 411 | "Integration", 412 | "IntegrationJsonApi", 413 | "IntegrationRole", 414 | "LandingPage", 415 | "LandingPageJsonApi", 416 | "LandingPageSalesChannel", 417 | "LandingPageTag", 418 | "Language", 419 | "LanguageJsonApi", 420 | "Locale", 421 | "LocaleJsonApi", 422 | "LogEntry", 423 | "LogEntryJsonApi", 424 | "MailHeaderFooter", 425 | "MailHeaderFooterJsonApi", 426 | "MailTemplate", 427 | "MailTemplateJsonApi", 428 | "MailTemplateMedia", 429 | "MailTemplateType", 430 | "MailTemplateTypeJsonApi", 431 | "MainCategory", 432 | "MainCategoryJsonApi", 433 | "MeasurementDisplayUnit", 434 | "MeasurementDisplayUnitJsonApi", 435 | "MeasurementSystem", 436 | "MeasurementSystemJsonApi", 437 | "MeasurementUnits", 438 | "Media", 439 | "MediaAiTag", 440 | "MediaAiTagJsonApi", 441 | "MediaDefaultFolder", 442 | "MediaDefaultFolderJsonApi", 443 | "MediaFolder", 444 | "MediaFolderConfiguration", 445 | "MediaFolderConfigurationJsonApi", 446 | "MediaFolderConfigurationMediaThumbnailSize", 447 | "MediaFolderJsonApi", 448 | "MediaJsonApi", 449 | "MediaTag", 450 | "MediaThumbnail", 451 | "MediaThumbnailJsonApi", 452 | "MediaThumbnailSize", 453 | "MediaThumbnailSizeJsonApi", 454 | "MultiNotFilter", 455 | "NewsletterRecipient", 456 | "NewsletterRecipientJsonApi", 457 | "NewsletterRecipientTag", 458 | "Notification", 459 | "NotificationJsonApi", 460 | "NumberRange", 461 | "NumberRangeJsonApi", 462 | "NumberRangeSalesChannel", 463 | "NumberRangeSalesChannelJsonApi", 464 | "NumberRangeState", 465 | "NumberRangeStateJsonApi", 466 | "NumberRangeType", 467 | "NumberRangeTypeJsonApi", 468 | "OAuthClientCredentialsGrant", 469 | "OAuthGrant", 470 | "OAuthPasswordGrant", 471 | "OAuthRefreshTokenGrant", 472 | "OAuthScopes", 473 | "Order", 474 | "OrderAddress", 475 | "OrderAddressJsonApi", 476 | "OrderCustomer", 477 | "OrderCustomerJsonApi", 478 | "OrderDelivery", 479 | "OrderDeliveryJsonApi", 480 | "OrderDeliveryPosition", 481 | "OrderDeliveryPositionJsonApi", 482 | "OrderJsonApi", 483 | "OrderLineItem", 484 | "OrderLineItemDownload", 485 | "OrderLineItemDownloadJsonApi", 486 | "OrderLineItemJsonApi", 487 | "OrderProductWarehouse", 488 | "OrderProductWarehouseJsonApi", 489 | "OrderReturn", 490 | "OrderReturnJsonApi", 491 | "OrderReturnLineItem", 492 | "OrderReturnLineItemJsonApi", 493 | "OrderReturnLineItemReason", 494 | "OrderReturnLineItemReasonJsonApi", 495 | "OrderTag", 496 | "OrderTransaction", 497 | "OrderTransactionCapture", 498 | "OrderTransactionCaptureJsonApi", 499 | "OrderTransactionCaptureRefund", 500 | "OrderTransactionCaptureRefundJsonApi", 501 | "OrderTransactionCaptureRefundPosition", 502 | "OrderTransactionCaptureRefundPositionJsonApi", 503 | "OrderTransactionJsonApi", 504 | "OrderWarehouseGroup", 505 | "OrderWarehouseGroupJsonApi", 506 | "PaymentMethod", 507 | "PaymentMethodJsonApi", 508 | "Plugin", 509 | "PluginJsonApi", 510 | "Price", 511 | "Product", 512 | "ProductCategory", 513 | "ProductCategoryTree", 514 | "ProductConfiguratorSetting", 515 | "ProductConfiguratorSettingJsonApi", 516 | "ProductCrossSelling", 517 | "ProductCrossSellingAssignedProducts", 518 | "ProductCrossSellingAssignedProductsJsonApi", 519 | "ProductCrossSellingJsonApi", 520 | "ProductCustomFieldSet", 521 | "ProductDownload", 522 | "ProductDownloadJsonApi", 523 | "ProductExport", 524 | "ProductExportJsonApi", 525 | "ProductFeatureSet", 526 | "ProductFeatureSetJsonApi", 527 | "ProductJsonApi", 528 | "ProductKeywordDictionary", 529 | "ProductKeywordDictionaryJsonApi", 530 | "ProductManufacturer", 531 | "ProductManufacturerJsonApi", 532 | "ProductMedia", 533 | "ProductMediaJsonApi", 534 | "ProductOption", 535 | "ProductPrice", 536 | "ProductPriceJsonApi", 537 | "ProductProperty", 538 | "ProductReview", 539 | "ProductReviewJsonApi", 540 | "ProductReviewSummary", 541 | "ProductReviewSummaryJsonApi", 542 | "ProductSearchConfig", 543 | "ProductSearchConfigField", 544 | "ProductSearchConfigFieldJsonApi", 545 | "ProductSearchConfigJsonApi", 546 | "ProductSearchKeyword", 547 | "ProductSearchKeywordJsonApi", 548 | "ProductSorting", 549 | "ProductSortingJsonApi", 550 | "ProductStream", 551 | "ProductStreamFilter", 552 | "ProductStreamFilterJsonApi", 553 | "ProductStreamJsonApi", 554 | "ProductStreamMapping", 555 | "ProductTag", 556 | "ProductVisibility", 557 | "ProductVisibilityJsonApi", 558 | "ProductWarehouse", 559 | "ProductWarehouseGroup", 560 | "ProductWarehouseJsonApi", 561 | "Promotion", 562 | "PromotionCartRule", 563 | "PromotionDiscount", 564 | "PromotionDiscountJsonApi", 565 | "PromotionDiscountPrices", 566 | "PromotionDiscountPricesJsonApi", 567 | "PromotionDiscountRule", 568 | "PromotionIndividualCode", 569 | "PromotionIndividualCodeJsonApi", 570 | "PromotionJsonApi", 571 | "PromotionOrderRule", 572 | "PromotionPersonaCustomer", 573 | "PromotionPersonaRule", 574 | "PromotionSalesChannel", 575 | "PromotionSalesChannelJsonApi", 576 | "PromotionSetgroup", 577 | "PromotionSetgroupJsonApi", 578 | "PromotionSetgroupRule", 579 | "PropertyGroup", 580 | "PropertyGroupJsonApi", 581 | "PropertyGroupOption", 582 | "PropertyGroupOptionJsonApi", 583 | "Quote", 584 | "QuoteComment", 585 | "QuoteCommentJsonApi", 586 | "QuoteDelivery", 587 | "QuoteDeliveryJsonApi", 588 | "QuoteDeliveryPosition", 589 | "QuoteDeliveryPositionJsonApi", 590 | "QuoteDocument", 591 | "QuoteDocumentJsonApi", 592 | "QuoteEmployee", 593 | "QuoteEmployeeJsonApi", 594 | "QuoteJsonApi", 595 | "QuoteLineItem", 596 | "QuoteLineItemJsonApi", 597 | "QuoteTransaction", 598 | "QuoteTransactionJsonApi", 599 | "RangeFilter", 600 | "Rule", 601 | "RuleCondition", 602 | "RuleConditionJsonApi", 603 | "RuleJsonApi", 604 | "RuleTag", 605 | "SalesChannel", 606 | "SalesChannelAnalytics", 607 | "SalesChannelAnalyticsJsonApi", 608 | "SalesChannelCountry", 609 | "SalesChannelCurrency", 610 | "SalesChannelDomain", 611 | "SalesChannelDomainJsonApi", 612 | "SalesChannelJsonApi", 613 | "SalesChannelLanguage", 614 | "SalesChannelPaymentMethod", 615 | "SalesChannelShippingMethod", 616 | "SalesChannelType", 617 | "SalesChannelTypeJsonApi", 618 | "Salutation", 619 | "SalutationJsonApi", 620 | "ScheduledTask", 621 | "ScheduledTaskJsonApi", 622 | "Script", 623 | "ScriptJsonApi", 624 | "SeoUrl", 625 | "SeoUrlJsonApi", 626 | "SeoUrlTemplate", 627 | "SeoUrlTemplateJsonApi", 628 | "ShippingMethod", 629 | "ShippingMethodJsonApi", 630 | "ShippingMethodPrice", 631 | "ShippingMethodPriceJsonApi", 632 | "ShippingMethodTag", 633 | "SimpleFilter", 634 | "Snippet", 635 | "SnippetJsonApi", 636 | "SnippetSet", 637 | "SnippetSetJsonApi", 638 | "Sort", 639 | "SpatialRenderConfigSize", 640 | "SpatialRenderConfigSizeJsonApi", 641 | "SpatialScene", 642 | "SpatialSceneCamera", 643 | "SpatialSceneCameraJsonApi", 644 | "SpatialSceneGroup", 645 | "SpatialSceneGroupJsonApi", 646 | "SpatialSceneJsonApi", 647 | "SpatialSceneLight", 648 | "SpatialSceneLightJsonApi", 649 | "SpatialSceneMaterial", 650 | "SpatialSceneMaterialJsonApi", 651 | "SpatialSceneObject", 652 | "SpatialSceneObjectJsonApi", 653 | "SpatialSceneObjectMaterial", 654 | "SpatialScenePrimitive", 655 | "SpatialScenePrimitiveJsonApi", 656 | "SsoProvider", 657 | "SsoProviderCustomer", 658 | "SsoProviderCustomerJsonApi", 659 | "SsoProviderJsonApi", 660 | "StateMachine", 661 | "StateMachineHistory", 662 | "StateMachineHistoryJsonApi", 663 | "StateMachineJsonApi", 664 | "StateMachineState", 665 | "StateMachineStateJsonApi", 666 | "StateMachineTransition", 667 | "StateMachineTransitionJsonApi", 668 | "SubAggregations", 669 | "Subscription", 670 | "SubscriptionAddress", 671 | "SubscriptionAddressJsonApi", 672 | "SubscriptionCustomer", 673 | "SubscriptionCustomerJsonApi", 674 | "SubscriptionInterval", 675 | "SubscriptionIntervalJsonApi", 676 | "SubscriptionJsonApi", 677 | "SubscriptionPlan", 678 | "SubscriptionPlanIntervalMapping", 679 | "SubscriptionPlanJsonApi", 680 | "SubscriptionPlanProductMapping", 681 | "SubscriptionTagMapping", 682 | "SwagDelayAction", 683 | "SwagDelayActionJsonApi", 684 | "SwagSequenceWebhookEventLog", 685 | "SystemConfig", 686 | "SystemConfigJsonApi", 687 | "Tag", 688 | "TagJsonApi", 689 | "Tax", 690 | "TaxJsonApi", 691 | "TaxProvider", 692 | "TaxProviderJsonApi", 693 | "TaxRule", 694 | "TaxRuleJsonApi", 695 | "TaxRuleType", 696 | "TaxRuleTypeJsonApi", 697 | "Theme", 698 | "ThemeChild", 699 | "ThemeJsonApi", 700 | "ThemeMedia", 701 | "ThemeSalesChannel", 702 | "Unit", 703 | "UnitJsonApi", 704 | "User", 705 | "UserAccessKey", 706 | "UserAccessKeyJsonApi", 707 | "UserConfig", 708 | "UserConfigJsonApi", 709 | "UserJsonApi", 710 | "UserRecovery", 711 | "UserRecoveryJsonApi", 712 | "Warehouse", 713 | "WarehouseGroup", 714 | "WarehouseGroupJsonApi", 715 | "WarehouseGroupWarehouse", 716 | "WarehouseJsonApi", 717 | "Webhook", 718 | "WebhookEventLog", 719 | "WebhookEventLogJsonApi", 720 | "WebhookJsonApi", 721 | "attributes", 722 | "businessEventsResponse", 723 | "data", 724 | "error", 725 | "failure", 726 | "flowBuilderActionsResponse", 727 | "info", 728 | "infoConfigResponse", 729 | "jsonapi", 730 | "link", 731 | "linkage", 732 | "links", 733 | "meta", 734 | "pagination", 735 | "relationshipLinks", 736 | "relationshipToMany", 737 | "relationshipToOne", 738 | "relationships", 739 | "resource", 740 | "success" 741 | ] 742 | } 743 | --------------------------------------------------------------------------------