diff --git a/adminapi.json b/adminapi.json index 8b17c32..54fd446 100644 --- a/adminapi.json +++ b/adminapi.json @@ -75769,6 +75769,77 @@ } } }, + "/_action/order/{orderId}/order-address": { + "post": { + "tags": [ + "Order address" + ], + "summary": "Update order addresses", + "description": "Endpoint which takes a list of mapping objects as payload and updates the order addresses accordingly", + "operationId": "updateOrderAddresses", + "parameters": [ + { + "name": "orderId", + "in": "path", + "description": "Identifier of the order.", + "required": true, + "schema": { + "type": "string", + "pattern": "^[0-9a-f]{32}$" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "mapping": { + "type": "array", + "items": { + "type": "object", + "properties": { + "customerAddressId": { + "type": "string", + "description": "The ID of the customer address" + }, + "type": { + "type": "string", + "description": "The type of the address" + }, + "deliveryId": { + "description": "The ID of the delivery (optional)", + "oneOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "customerAddressId", + "type" + ] + }, + "description": "The mapping of order addresses" + } + } + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "Returns a no content response indicating that the update has been made." + } + } + } + }, "/_action/validation/email": { "post": { "tags": [ @@ -75855,6 +75926,410 @@ } } }, + "/_action/indexing": { + "post": { + "tags": [ + "System Operations" + ], + "summary": "Run indexer", + "description": "Runs all registered indexer in the shop asynchronously.", + "operationId": "indexing", + "responses": { + "200": { + "description": "Returns an empty response indicating that the indexing process started." + } + } + } + }, + "/_action/indexing/{indexer}": { + "post": { + "tags": [ + "System Operations" + ], + "summary": "Iterate an indexer", + "description": "Starts a defined indexer with an offset.\n\nfor the next request. `finish: true` in the response indicates that the indexer is finished", + "operationId": "iterate", + "parameters": [ + { + "name": "indexer", + "in": "path", + "description": "Name of the indexer to iterate.", + "required": true, + "schema": { + "type": "string", + "pattern": "^[0-9a-f]{32}$" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "properties": { + "offset": { + "description": "The offset for the iteration.", + "type": "integer" + } + }, + "type": "object" + } + } + } + }, + "responses": { + "200": { + "description": "Returns information about the iteration.", + "content": { + "application/json": { + "schema": { + "properties": { + "finish": { + "description": "Indicates if the indexing process finished.", + "type": "boolean" + }, + "offset": { + "description": "Offset to be used for the next iteration.", + "type": "integer" + } + }, + "type": "object" + } + } + } + } + } + } + }, + "/_info/message-stats.json": { + "get": { + "summary": "Get statistics message queue", + "description": "Get statistics for recently processed messages in the message queue", + "operationId": "getMessageStats", + "tags": [ + "System Info & Health Check" + ], + "responses": { + "200": { + "description": "Statistics received", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "enabled" + ], + "properties": { + "enabled": { + "type": "boolean", + "description": "Whether message queue statistics are enabled in configuration" + }, + "stats": { + "type": [ + "object", + "null" + ], + "properties": { + "totalMessagesProcessed": { + "type": "integer" + }, + "processedSince": { + "type": "string", + "format": "date-time" + }, + "averageTimeInQueue": { + "type": "number", + "format": "float" + }, + "messageTypeStats": { + "type": "array", + "items": { + "type": "object", + "properties": { + "type": { + "type": "string" + }, + "count": { + "type": "integer" + } + } + } + } + } + } + } + } + } + } + } + } + } + }, + "/_info/flow-actions.json": { + "get": { + "tags": [ + "System Info & Health Check" + ], + "summary": "Get actions for flow builder", + "description": "Get a list of action for flow builder.", + "operationId": "flow-actions", + "responses": { + "200": { + "description": "Returns a list of action for flow builder.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/flowBuilderActionsResponse" + } + } + } + } + } + } + }, + "/_info/version": { + "get": { + "tags": [ + "System Info & Health Check" + ], + "summary": "Get the Shopware version", + "description": "Get the version of the Shopware instance", + "operationId": "infoShopwareVersion", + "responses": { + "200": { + "description": "Returns the version of the Shopware instance.", + "content": { + "application/json": { + "schema": { + "properties": { + "version": { + "description": "The Shopware version.", + "type": "string" + } + }, + "type": "object" + } + } + } + } + } + } + }, + "/_info/health-check": { + "get": { + "tags": [ + "System Info & Health Check" + ], + "summary": "Check that the Application is running", + "operationId": "healthCheck", + "responses": { + "200": { + "description": "Returns empty response" + }, + "500": { + "description": "Application is not working properly" + } + } + } + }, + "/_info/system-health-check": { + "get": { + "tags": [ + "System Info & Health Check" + ], + "summary": "Perform a detailed system health check", + "operationId": "systemHealthCheck", + "parameters": [ + { + "name": "verbose", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "default": false + }, + "description": "Include detailed information in the response" + } + ], + "responses": { + "200": { + "description": "Returns the system health check results", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "checks": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "healthy": { + "type": "boolean" + }, + "status": { + "type": "string" + }, + "message": { + "type": "string" + }, + "extra": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": true + } + } + } + } + } + } + } + } + } + }, + "500": { + "description": "Application is not working properly" + } + } + } + }, + "/_action/cache_info": { + "get": { + "tags": [ + "System Operations" + ], + "summary": "Get cache information", + "description": "Get information about the cache configuration", + "operationId": "info", + "responses": { + "200": { + "description": "Information about the cache state.", + "content": { + "application/json": { + "schema": { + "properties": { + "environment": { + "description": "The active environment.", + "type": "string" + }, + "httpCache": { + "description": "State of the HTTP cache.", + "type": "boolean" + }, + "cacheAdapter": { + "description": "The active cache adapter.", + "type": "string" + } + }, + "type": "object" + } + } + } + } + } + } + }, + "/_action/order_delivery/{orderDeliveryId}/state/{transition}": { + "post": { + "tags": [ + "Order Management" + ], + "summary": "Transition an order delivery to a new state", + "description": "Changes the order delivery state and informs the customer via email if configured.", + "operationId": "orderDeliveryStateTransition", + "parameters": [ + { + "name": "orderDeliveryId", + "in": "path", + "description": "Identifier of the order delivery.", + "required": true, + "schema": { + "type": "string", + "pattern": "^[0-9a-f]{32}$" + } + }, + { + "name": "transition", + "in": "path", + "description": "The `action_name` of the `state_machine_transition`. For example `process` if the order state should change from open to in progress.\n\nNote: If you choose a transition which is not possible, you will get an error that lists possible transition for the actual state.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "properties": { + "sendMail": { + "description": "Controls if a mail should be send to the customer." + }, + "documentIds": { + "description": "A list of document identifiers that should be attached", + "type": "array", + "items": { + "type": "string", + "pattern": "^[0-9a-f]{32}$" + } + }, + "mediaIds": { + "description": "A list of media identifiers that should be attached", + "type": "array", + "items": { + "type": "string", + "pattern": "^[0-9a-f]{32}$" + } + }, + "stateFieldName": { + "description": "This is the state column within the order delivery database table. There should be no need to change it from the default.", + "type": "string", + "default": "stateId" + }, + "internalComment": { + "description": "An optional internal comment that will be saved with the state transition.", + "type": "string" + } + }, + "type": "object" + } + } + } + }, + "responses": { + "200": { + "description": "Todo: Use ref of `state_machine_transition` here" + } + } + } + }, + "/_info/events.json": { + "get": { + "tags": [ + "System Info & Health Check" + ], + "summary": "Get Business events", + "description": "Get a list of about the business events.", + "operationId": "business-events", + "responses": { + "200": { + "description": "Returns a list of about the business events.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/businessEventsResponse" + } + } + } + } + } + } + }, "/_info/config": { "get": { "tags": [ @@ -75963,143 +76438,91 @@ } } }, - "/app-system/privileges/requested": { + "/_action/document/{documentId}/{deepLinkCode}": { "get": { "tags": [ - "App System" + "Document Management" ], - "summary": "Get requested privileges for all apps", - "description": "Returns the list of requested privileges for all apps. Requires admin scope and `acl_role:read` permission to read.", - "operationId": "getRequestedPrivileges", - "security": [ + "summary": "Download a document", + "description": "Download a document by its identifier and deep link code.", + "operationId": "downloadDocument", + "parameters": [ { - "oAuth": [ - "admin" - ] - } - ], - "responses": { - "200": { - "description": "A JSON object containing requested privileges.", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "privileges": { - "type": "object", - "additionalProperties": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - }, - "example": { - "privileges": { - "SwagAnalytics": [ - "customer:read", - "order:read" - ], - "SwagExample": [ - "product:write" - ] - } - } - } + "name": "documentId", + "in": "path", + "description": "Identifier of the document to be downloaded.", + "required": true, + "schema": { + "type": "string", + "pattern": "^[0-9a-f]{32}$" } }, - "400": { - "description": "Malformed request." - }, - "401": { - "description": "Unauthorized Access." - }, - "403": { - "description": "Forbidden. Not a valid integration source." - } - } - } - }, - "/app-system/{appName}/privileges/accepted": { - "get": { - "tags": [ - "App System" - ], - "summary": "Get accepted privileges for an app", - "description": "Returns the list of accepted privileges for the current integration. Requires admin scope with an integration.", - "operationId": "getAcceptedPrivileges", - "parameters": [ { - "name": "appName", + "name": "deepLinkCode", "in": "path", + "description": "A unique hash code which was generated when the document was created.", "required": true, "schema": { "type": "string" } - } - ], - "security": [ + }, { - "oAuth": [ - "admin" - ] + "name": "download", + "in": "query", + "description": "This parameter controls the `Content-Disposition` header. If set to `true` the header will be set to `attachment` else `inline`.", + "schema": { + "type": "boolean", + "default": false + } } ], "responses": { "200": { - "description": "A JSON object containing accepted privileges.", + "description": "The document.", "content": { - "application/json": { + "application/octet-stream": { "schema": { - "type": "object", - "properties": { - "privileges": { - "type": "object", - "additionalProperties": { - "type": "boolean" - } - } - } - }, - "example": { - "privileges": { - "customer:read": true, - "order:read": true - } + "type": "string", + "format": "binary" } } } - }, - "400": { - "description": "Malformed request." - }, - "401": { - "description": "Unauthorized Access." - }, - "403": { - "description": "Forbidden. Not a valid integration source." - }, - "404": { - "description": "App not found." } } } }, - "/app-system/{appName}/privileges": { - "patch": { + "/_action/document/{documentId}/upload": { + "post": { "tags": [ - "App System" + "Document Management" ], - "summary": "Accept or revoke privileges for an app", - "description": "Accepts or revokes specified privileges for the given app.", - "operationId": "managePrivileges", + "summary": "Upload a file for a document", + "description": "Uploads a file for a document. This prevents the document from being dynamically generated and delivers the uploaded file instead, when the document is downloaded.\n\nNote:\n* The document is required to be `static`\n* A document can only have one media file\n\nThe are two methods of providing a file to this route:\n * Use a typical file upload and provide the file in the request\n * Fetch the file from an url. This only works if the `shopware.media.enable_url_upload_feature` variable is set to true in the shop environment.\nTo use file upload via url, the content type has to be `application/json` and the parameter `url` has to be provided.", + "operationId": "uploadToDocument", "parameters": [ { - "name": "appName", + "name": "documentId", "in": "path", + "description": "Identifier of the document the new file should be added to.", + "required": true, + "schema": { + "type": "string", + "pattern": "^[0-9a-f]{32}$" + } + }, + { + "name": "fileName", + "in": "query", + "description": "Name of the uploaded file.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "extension", + "in": "query", + "description": "Extension of the uploaded file. For example `pdf`", "required": true, "schema": { "type": "string" @@ -76107,194 +76530,103 @@ } ], "requestBody": { - "required": true, "content": { + "application/octet-stream": { + "schema": { + "type": "string", + "format": "binary" + } + }, "application/json": { "schema": { - "type": "object", + "required": [ + "url" + ], "properties": { - "accept": { - "type": "array", - "items": { - "type": "string" - } - }, - "revoke": { - "type": "array", - "items": { - "type": "string" - } + "url": { + "description": "The url of the document that will be downloaded.", + "type": "string" } - } - }, - "example": { - "accept": [ - "customer:read", - "order:read" - ], - "revoke": [ - "product:write" - ] + }, + "type": "object" } } } }, "responses": { - "204": { - "description": "Returns no content if privileges were managed successfully." - }, - "400": { - "description": "Malformed request." - }, - "401": { - "description": "Unauthorized Access." - }, - "403": { - "description": "Forbidden. Not a valid integration source." - }, - "404": { - "description": "App not found." - } - }, - "security": [ - { - "oAuth": [ - "admin" - ] + "200": { + "description": "Document uploaded successful", + "content": { + "application/json": { + "schema": { + "properties": { + "documentId": { + "description": "Identifier of the document.", + "type": "string", + "pattern": "^[0-9a-f]{32}$" + }, + "documentDeepLink": { + "description": "A unique hash code which is required to open the document.", + "type": "string" + } + }, + "type": "object" + } + } + } } - ] + } } }, - "/_action/app-system/secret/rotate": { + "/_action/scheduled-task/run": { "post": { "tags": [ - "App System" + "System Operations" ], - "summary": "Initiate secret rotation for the calling app", - "description": "Initiates an app secret rotation for the calling app. Needs to be called with an integration token belonging to an app. Note that the secret rotation will only be scheduled and then handled asynchronously.", - "operationId": "appSecretRotation", + "summary": "Run scheduled tasks.", + "description": "Starts the scheduled task worker to handle the next scheduled tasks.", + "operationId": "runScheduledTasks", "responses": { - "202": { - "description": "Returns \"Accepted\" when secret rotation was scheduled." - }, - "400": { - "description": "Malformed request, e.g. when requested with non app integration source." - }, - "401": { - "description": "Unauthorized Access." - }, - "403": { - "description": "Forbidden. Not a valid integration source." - }, - "404": { - "description": "App not found." - } - }, - "security": [ - { - "oAuth": [ - "admin" - ] - } - ] - } - }, - "/app-system/shop/verify": { - "get": { - "tags": [ - "App System", - "Public" - ], - "summary": "Verify a shop's APP_URL", - "description": "Used to verify that a shop's APP_URL points to its self. The passed run ID and token are used to query the cache. It returns 204 no content if the given token can be verified using the run id.", - "operationId": "verifyAppUrl", - "parameters": [ - { - "name": "runId", - "in": "query", - "description": "A unique identifier used to look up the token", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "token", - "in": "query", - "description": "A unique identifier", - "required": true, - "schema": { - "type": "string" + "200": { + "description": "Returns a success message indicating a successful run.", + "content": { + "application/json": { + "schema": { + "properties": { + "message": { + "description": "Success message", + "type": "string" + } + }, + "type": "object" + } + } } } - ], - "responses": { - "204": { - "description": "An empty response signalling successful verification." - }, - "400": { - "description": "Malformed request or unsuccessful verification." - } } } }, - "/_info/message-stats.json": { + "/_action/scheduled-task/min-run-interval": { "get": { - "summary": "Get statistics message queue", - "description": "Get statistics for recently processed messages in the message queue", - "operationId": "getMessageStats", "tags": [ - "System Info & Health Check" + "System Operations" ], + "summary": "Get the minimum schedules task interval", + "description": "Fetches the smallest interval that a scheduled task uses.", + "operationId": "getMinRunInterval", "responses": { "200": { - "description": "Statistics received", + "description": "Returns the minimum interval.", "content": { "application/json": { "schema": { - "type": "object", - "required": [ - "enabled" - ], "properties": { - "enabled": { - "type": "boolean", - "description": "Whether message queue statistics are enabled in configuration" - }, - "stats": { - "type": [ - "object", - "null" - ], - "properties": { - "totalMessagesProcessed": { - "type": "integer" - }, - "processedSince": { - "type": "string", - "format": "date-time" - }, - "averageTimeInQueue": { - "type": "number", - "format": "float" - }, - "messageTypeStats": { - "type": "array", - "items": { - "type": "object", - "properties": { - "type": { - "type": "string" - }, - "count": { - "type": "integer" - } - } - } - } - } + "minRunInterval": { + "description": "Minimal interval in seconds.", + "type": "string" } - } + }, + "type": "object" } } } @@ -76302,326 +76634,234 @@ } } }, - "/_action/system-config": { - "get": { + "/_action/order_transaction_capture_refund/{refundId}": { + "post": { "tags": [ - "System Config" + "Order Management" ], - "summary": "Get configuration values", - "description": "Returns the configuration values for the given domain and optional sales channel.", - "operationId": "getConfigurationValues", + "summary": "Refund an order transaction capture", + "description": "Refunds an order transaction capture.", + "operationId": "orderTransactionCaptureRefund", "parameters": [ { - "name": "domain", - "in": "query", - "description": "The configuration domain.", + "name": "refundId", + "in": "path", + "description": "Identifier of the order transaction capture refund.", "required": true, "schema": { - "type": "string" - } - }, - { - "name": "salesChannelId", - "in": "query", - "description": "The sales channel ID to scope the configuration to.", - "schema": { - "type": "string" - } - }, - { - "name": "inherit", - "in": "query", - "description": "Whether to include inherited (global) values.", - "schema": { - "type": "boolean", - "default": false + "type": "string", + "pattern": "^[0-9a-f]{32}$" } } ], "responses": { - "200": { - "description": "Returns the configuration values as a key-value object." + "204": { + "description": "Refund was successful" + }, + "400": { + "description": "Something went wrong, while processing the refund" + }, + "404": { + "description": "Refund with id not found" } } - }, + } + }, + "/_action/user/logout": { "post": { "tags": [ - "System Config" + "Authorization & Authentication" ], - "summary": "Save configuration values", - "description": "Saves the given configuration key-value pairs for the given sales channel.", - "operationId": "saveConfiguration", - "parameters": [ - { - "name": "salesChannelId", - "in": "query", - "description": "The sales channel ID to scope the configuration to.", - "schema": { - "type": "string" - } + "summary": "Logout the current user", + "description": "Revokes all server-side refresh tokens for the currently authenticated administration user and returns a no content response.", + "operationId": "userLogout", + "responses": { + "204": { + "description": "Tokens have been revoked successfully." }, - { - "name": "silent", - "in": "query", - "description": "If true, the HTTP cache will not be invalidated. Use this for internal configuration values that do not affect the storefront.", - "schema": { - "type": "boolean", - "default": false - } + "401": { + "description": "Unauthorized - the access token is missing or invalid." + }, + "403": { + "description": "The authenticated source does not have a user ID associated." } + } + } + }, + "/_action/order/document/download": { + "post": { + "tags": [ + "Document Management" ], + "summary": "Download a documents", + "description": "Download a multiple documents in one pdf file.", + "operationId": "downloadDocuments", "requestBody": { - "description": "Key-value pairs of configuration values to save.", - "required": true, + "description": "documentIds", "content": { "application/json": { "schema": { - "type": "object", - "additionalProperties": true + "type": "array", + "items": { + "type": "string", + "pattern": "^[0-9a-f]{32}$" + } } } } }, - "responses": { - "204": { - "description": "Configuration saved successfully." - } - } - } - }, - "/_action/system-config/check": { - "get": { - "tags": [ - "System Config" - ], - "summary": "Check configuration", - "description": "Checks if a configuration domain exists.", - "operationId": "checkConfiguration", - "parameters": [ - { - "name": "domain", - "in": "query", - "description": "The configuration domain to check.", - "required": true, - "schema": { - "type": "string" - } - } - ], "responses": { "200": { - "description": "Returns whether the configuration domain exists." + "description": "The documents.", + "content": { + "application/octet-stream": { + "schema": { + "type": "string", + "format": "binary" + } + } + } } } } }, - "/_action/system-config/schema": { - "get": { + "/_action/order/document/{documentTypeName}/create": { + "post": { "tags": [ - "System Config" + "Document Management" ], - "summary": "Get configuration schema", - "description": "Returns the configuration schema for the given domain.", - "operationId": "getConfiguration", + "summary": "Create documents for orders", + "description": "Creates documents for orders. Documents can for example be an invoice or a delivery note.", + "operationId": "createDocuments", "parameters": [ { - "name": "domain", - "in": "query", - "description": "The configuration domain.", + "name": "documentTypeName", + "in": "path", + "description": "The type of document to create", "required": true, "schema": { "type": "string" } } ], - "responses": { - "200": { - "description": "Returns the configuration schema." - } - } - } - }, - "/_action/system-config/batch": { - "post": { - "tags": [ - "System Config" - ], - "summary": "Batch save configuration values", - "description": "Saves configuration values for multiple sales channels at once. The request body is keyed by sales channel ID (use \"null\" for global scope).", - "operationId": "batchSaveConfiguration", - "parameters": [ - { - "name": "silent", - "in": "query", - "description": "If true, the HTTP cache will not be invalidated. Use this for internal configuration values that do not affect the storefront.", - "schema": { - "type": "boolean", - "default": false - } - } - ], "requestBody": { - "description": "Object keyed by sales channel ID, each containing key-value pairs of configuration values.", + "description": "test", "required": true, "content": { "application/json": { "schema": { - "type": "object", - "additionalProperties": { + "type": "array", + "items": { "type": "object", - "additionalProperties": true + "required": [ + "orderId", + "type" + ], + "properties": { + "orderId": { + "description": "Identifier of the order.", + "type": "string", + "pattern": "^[0-9a-f]{32}$" + }, + "type": { + "description": "Type of the document to be generated.", + "type": "string" + }, + "fileType": { + "description": "Type of document file to be generated.", + "type": "string", + "default": "pdf" + }, + "static": { + "description": "Indicate if the document should be static or not.", + "type": "boolean", + "default": false + }, + "referencedDocumentId": { + "description": "Identifier of the reverenced document.", + "type": "string", + "default": "null", + "pattern": "^[0-9a-f]{32}$" + }, + "config": { + "description": "Document specific configuration, like documentNumber, documentDate, documentComment.", + "type": "object" + } + } } } } } }, "responses": { - "204": { - "description": "Configuration saved successfully." + "200": { + "description": "Documents created successfully. The `api/_action/order/document/create` route can be used to download the document." } } } }, - "/_action/mail-template/send": { + "/_action/order/{orderId}/state/{transition}": { "post": { "tags": [ - "Mail Operations" + "Order Management" + ], + "summary": "Transition an order to a new state", + "description": "Changes the order state and informs the customer via email if configured.", + "operationId": "orderStateTransition", + "parameters": [ + { + "name": "orderId", + "in": "path", + "description": "Identifier of the order.", + "required": true, + "schema": { + "type": "string", + "pattern": "^[0-9a-f]{32}$" + } + }, + { + "name": "transition", + "in": "path", + "description": "The `action_name` of the `state_machine_transition`. For example `process` if the order state should change from open to in progress.\n\nNote: If you choose a transition that is not available, you will get an error that lists possible transitions for the current state.", + "required": true, + "schema": { + "type": "string" + } + } ], - "summary": "Send a mail", - "description": "Generates a mail from a mail template and sends it to the customer.\n\nTake a look at the `salesChannel` entity for possible values. For example `{{ salesChannel.name }}` can be used.", - "operationId": "send", "requestBody": { - "required": true, + "required": false, "content": { "application/json": { "schema": { - "required": [ - "recipients", - "salesChannelId", - "contentHtml", - "contentPlain", - "subject", - "senderName" - ], "properties": { - "recipients": { - "description": "A list of recipients with name and mail address.", - "type": "object", - "example": { - "test1@example.com": "Test user 1", - "test2@example.com": "Test user 2" - }, - "additionalProperties": { - "description": "Name of the recipient.", - "type": "string" - } - }, - "salesChannelId": { - "description": "Identifier of the sales channel from which the mail should be send.", - "type": "string", - "pattern": "^[0-9a-f]{32}$" - }, - "contentHtml": { - "description": "The content of the mail in HTML format.", - "type": "string" - }, - "contentPlain": { - "description": "The content of the mail as plain text.", - "type": "string" - }, - "subject": { - "description": "Subject of the mail.", - "type": "string" - }, - "senderName": { - "description": "Name of the sender.", - "type": "string" - }, - "senderEmail": { - "description": "Mail address of the sender. If not set, `core.basicInformation.email` or `core.mailerSettings.senderAddress` will be used from the shop configuration.", - "type": "string" + "sendMail": { + "description": "Controls if a mail should be sent to the customer." }, - "mediaIds": { - "description": "List of media identifiers which should be attached to the mail.", + "documentIds": { + "description": "A list of document identifiers that should be attached", "type": "array", "items": { "type": "string", "pattern": "^[0-9a-f]{32}$" } }, - "binAttachments": { - "description": "A list of binary attachments which should be added to the mail.", - "required": [ - "content", - "fileName", - "mimeType" - ], + "mediaIds": { + "description": "A list of media identifiers that should be attached", "type": "array", "items": { - "properties": { - "content": { - "description": "Binary content of the attachment.", - "type": "string" - }, - "fileName": { - "description": "File name of the attachment.", - "type": "string" - }, - "mimeType": { - "description": "Mime type of the attachment.", - "type": "string" - } - }, - "type": "object" - } - }, - "recipientsBcc": { - "description": "A list of recipients with name and mail address to be set in BCC.", - "type": "object", - "example": { - "test1@example.com": "Test user 1", - "test2@example.com": "Test user 2" - }, - "additionalProperties": { - "description": "Name of the recipient.", - "type": "string" - } - }, - "recipientsCc": { - "description": "A list of recipients with name and mail address to be set in CC.", - "type": "object", - "example": { - "test1@example.com": "Test user 1", - "test2@example.com": "Test user 2" - }, - "additionalProperties": { - "description": "Name of the recipient.", - "type": "string" + "type": "string", + "pattern": "^[0-9a-f]{32}$" } }, - "replyTo": { - "description": "A list of mail addresses with name and mail address to be set in reply to.", - "type": "object", - "example": { - "test1@example.com": "Test user 1", - "test2@example.com": "Test user 2" - }, - "additionalProperties": { - "description": "Name of the recipient.", - "type": "string" - } + "stateFieldName": { + "description": "This is the state column within the order database table. There should be no need to change it from the default.", + "type": "string", + "default": "stateId" }, - "returnPath": { - "description": "A list of mail addresses with name and mail address to be set in return path.", - "type": "object", - "example": { - "test1@example.com": "Test user 1", - "test2@example.com": "Test user 2" - }, - "additionalProperties": { - "description": "Name of the recipient.", - "type": "string" - } + "internalComment": { + "description": "An optional internal comment that will be saved with the state transition.", + "type": "string" } }, "type": "object" @@ -76631,479 +76871,491 @@ }, "responses": { "200": { - "description": "The mail was sent successful", + "description": "Todo: Use ref of `state_machine_transition` here" + } + } + } + }, + "/consents": { + "get": { + "tags": [ + "Consent Management", + "Experimental" + ], + "summary": "List all consents for current user", + "description": "Returns a list of all available consents with their current status for the authenticated admin user. Each consent includes its name, identifier, and current state (requested, accepted, or revoked). Experimental API, not part of our backwards compatibility promise, thus this API can introduce breaking changes at any time.", + "operationId": "fetchConsents", + "responses": { + "200": { + "description": "List of consents with their status", "content": { "application/json": { "schema": { - "properties": { - "size": { - "description": "Length of the email message", - "type": "integer" - } + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/ConsentState" }, - "type": "object" + "example": { + "product_analytics": { + "name": "product_analytics", + "scopeName": "admin_user", + "identifier": "userId-12345", + "status": "accepted", + "actor": "userId-12345", + "updatedAt": "2024-01-15T10:20:30Z", + "acceptedUntil": "2024-01-15T10:20:30Z", + "acceptedRevision": "2026-02-01", + "latestRevision": "2026-02-01" + }, + "backend_data": { + "name": "backend_data", + "scopeName": "system", + "identifier": "system", + "status": "unset", + "actor": null, + "updatedAt": null, + "acceptedUntil": null, + "acceptedRevision": null, + "latestRevision": null + } + } } } } + }, + "401": { + "description": "Unauthorized - User not logged in or invalid session" } } } }, - "/_action/mail-template/validate": { + "/consents/accept": { "post": { "tags": [ - "Mail Operations" + "Consent Management", + "Experimental" ], - "summary": "Validate a mail content", - "description": "Validates if content for a mail can be rendered without sending an email.", - "operationId": "validate", + "summary": "Accept a consent", + "description": "Marks the specified consent as accepted for the authenticated admin user. Experimental API, not part of our backwards compatibility promise, thus this API can introduce breaking changes at any time.", + "operationId": "acceptConsent", "requestBody": { - "required": true, "content": { "application/json": { "schema": { - "required": [ - "contentHtml", - "contentPlain" - ], + "type": "object", "properties": { - "contentHtml": { - "description": "The content of the mail in HTML format.", - "type": "string" + "consent": { + "type": "string", + "description": "The name of the consent to accept" }, - "contentPlain": { - "description": "The content of the mail as plain text.", - "type": "string" + "revision": { + "type": [ + "string", + "null" + ], + "description": "Optional accepted revision. Only the consent definition's latest revision is accepted. When omitted, the latest revision is used automatically." } }, - "type": "object" + "required": [ + "consent" + ], + "example": { + "consent": "product_analytics", + "revision": "2026-02-01" + } } } } }, "responses": { - "204": { - "description": "Returns a no content response indicating the mail content was rendered successfully." + "200": { + "description": "Consent status changed successfully. Returns the updated consent status.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ConsentState" + } + } + } + }, + "400": { + "description": "Bad request - Consent revision is invalid for current acceptance" + }, + "404": { + "description": "Bad request - Consent not found or consent property was empty" + }, + "401": { + "description": "Unauthorized - User not logged in or invalid session" } } } }, - "/_action/mail-template/build": { + "/consents/revoke": { "post": { "tags": [ - "Mail Operations" + "Consent Management", + "Experimental" ], - "summary": "Preview a mail template", - "description": "Generates a preview of a mail template.", - "operationId": "build", + "summary": "Revoke a consent", + "description": "Marks the specified consent as revoked for the authenticated admin user. Experimental API, not part of our backwards compatibility promise, thus this API can introduce breaking changes at any time.", + "operationId": "revokeConsent", "requestBody": { - "required": true, "content": { "application/json": { "schema": { - "required": [ - "mailTemplateType", - "mailTemplate" - ], + "type": "object", "properties": { - "mailTemplateType": { - "description": "Only the property `templateData` is used. It provides additional variables to the templating engine.", - "properties": { - "templateData": { - "description": "An associative array that is handed over to the templating engine and can be used as variables in the mail content.", - "type": "object", - "example": { - "order": { - "orderNumber": 5000, - "customerName": "Example Customer" - }, - "messageOfTheDay": "An apple a day keeps the doctor away!" - }, - "additionalProperties": true - } - }, - "type": "object" - }, - "mailTemplate": { - "description": "The content of the mail as plain text.", - "properties": { - "contentHtml": { - "description": "The content of mail mail template in html format.", - "type": "string", - "example": "Hello {{ order.customerName }}, this is example mail content, the current date is {{ 'now'|date('d/m/Y') }}" - } - }, - "type": "object" + "consent": { + "type": "string", + "description": "The name of the consent to accept" } }, - "type": "object" + "required": [ + "consent" + ], + "example": { + "consent": "product_analytics" + } } } } }, "responses": { "200": { - "description": "The rendered preview of the mail template.", + "description": "Consent status changed successfully. Returns the updated consent status.", "content": { "application/json": { "schema": { - "type": "string" + "$ref": "#/components/schemas/ConsentState" } } } + }, + "404": { + "description": "Bad request - Consent not found or consent property was empty" + }, + "401": { + "description": "Unauthorized - User not logged in or invalid session" } } } }, - "/_action/media/{mediaId}/upload": { - "post": { + "/_action/number-range/reserve/{type}/{saleschannel}": { + "get": { "tags": [ - "Asset Management" + "Document Management" ], - "summary": "Upload a file to a media entity", - "description": "Adds a new file to a media entity. If the entity has an existing file, it will be replaced.\n\nThe are two methods of providing a file to this route:\n * Use a typical file upload and provide the file in the request\n * Fetch the file from an url. This only works if the `shopware.media.enable_url_upload_feature` variable is set to true in the shop environment.\nTo use file upload via url, the content type has to be `application/json` and the parameter `url` has to be provided.", - "operationId": "upload", + "summary": "Reserve or preview a number-range / document number.", + "description": "This endpoint provides functionality to reserve or preview a document number which can be used to create a new document using the `/_action/order/{orderId}/document/{documentTypeName}` endpoint.\n\nThe number generated by the endpoint will be reserved and the number pointer will be incremented with every call. For preview purposes, you can add the `?preview=1` parameter to the request. In that case, the number will not be incremented.", + "operationId": "numberRangeReserve", "parameters": [ { - "name": "mediaId", + "name": "type", "in": "path", - "description": "Identifier of the media entity.", + "description": "`technicalName` of the document type (e.g. `document_invoice`). Available types can be fetched with the `/api/document-type endpoint`.", "required": true, "schema": { - "$ref": "#/components/schemas/MediaId" + "type": "string" } }, { - "name": "fileName", - "in": "query", - "description": "Name of the uploaded file. If not provided the media identifier will be used as name", + "name": "saleschannel", + "in": "path", + "description": "Sales channel for the number range. Number ranges can be defined per sales channel, so you can pass a sales channel ID here.", + "required": true, "schema": { "type": "string" } }, { - "name": "extension", + "name": "preview", "in": "query", - "description": "Extension of the uploaded file. For example `png`", + "description": "If this parameter has a true value, the number will not actually be incremented, but only previewed.", + "required": false, + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "The generated number", + "content": { + "application/json": { + "schema": { + "properties": { + "number": { + "description": "The generated (or previewed) document number.", + "type": "string" + } + }, + "type": "object" + } + } + } + }, + "400": { + "description": "Number range not found" + } + } + } + }, + "/_action/increment/{pool}": { + "post": { + "tags": [ + "Increment Storage" + ], + "summary": "Increment a value in the specified pool", + "description": "Increments a value by key in the specified increment pool. This operation increments the counter for the given key and returns a success response.", + "operationId": "incrementValue", + "parameters": [ + { + "name": "pool", + "in": "path", + "description": "The name of the increment pool (e.g., 'user_activity', 'message_queue').", "required": true, "schema": { "type": "string" } + }, + { + "name": "cluster", + "in": "query", + "description": "Optional cluster identifier for the increment operation.", + "required": false, + "schema": { + "type": "string" + } } ], "requestBody": { + "required": true, "content": { - "application/octet-stream": { - "schema": { - "type": "string", - "format": "binary" - } - }, "application/json": { "schema": { + "type": "object", "required": [ - "url" + "key" ], "properties": { - "url": { - "description": "The url of the media file that will be downloaded.", - "type": "string" + "key": { + "type": "string", + "description": "The key to increment in the pool." } - }, - "type": "object" + } } } } }, "responses": { - "204": { - "description": "Media file uploaded successful", - "headers": { - "Location": { - "description": "Contains the url to the uploaded media for a redirect.", + "200": { + "description": "Successfully incremented the value", + "content": { + "application/json": { "schema": { - "type": "string" + "type": "object", + "properties": { + "success": { + "type": "boolean", + "example": true + } + } } } } + }, + "400": { + "description": "Bad request - key parameter missing or cluster parameter missing" } } - } - }, - "/_action/media/upload": { - "post": { + }, + "get": { "tags": [ - "Asset Management" + "Increment Storage" ], - "summary": "Upload a new media file", - "description": "Creates a new media entity and uploads a file to it using form-data file upload.", - "operationId": "uploadV2", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "type": "object", - "properties": { - "file": { - "type": "string", - "format": "binary", - "description": "The file to upload" - }, - "id": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "Custom ID for the media entity" - }, - "fileName": { - "type": "string", - "description": "Name of the uploaded file" - }, - "private": { - "type": "boolean", - "description": "Whether the media should be private" - }, - "mediaFolderId": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "ID of the media folder" - }, - "mimeType": { - "type": "string", - "description": "MIME type of the file" - }, - "deduplicate": { - "type": "boolean", - "description": "Whether to deduplicate based on file hash" - } - }, - "required": [ - "file" - ] - } + "summary": "List increment values from pool", + "description": "Retrieves a list of increment values from the specified pool with pagination support.", + "operationId": "getIncrementValues", + "parameters": [ + { + "name": "pool", + "in": "path", + "description": "The name of the increment pool to list values from.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "cluster", + "in": "query", + "description": "Cluster identifier for the increment operation.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "description": "Maximum number of items to return.", + "required": false, + "schema": { + "type": "integer", + "default": 5, + "minimum": 1 + } + }, + { + "name": "offset", + "in": "query", + "description": "Number of items to skip for pagination.", + "required": false, + "schema": { + "type": "integer", + "default": 0, + "minimum": 0 } } - }, + ], "responses": { "200": { - "description": "Media file uploaded successfully", + "description": "List of increment values", "content": { - "application\\/json": { + "application/json": { "schema": { - "type": "object", - "properties": { - "id": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "ID of the created media entity" + "type": "array", + "items": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "The increment key" + }, + "count": { + "type": "integer", + "description": "The current count value" + } } } } } } + }, + "400": { + "description": "Bad request - cluster parameter missing" } } } }, - "/_action/media/upload_by_url": { + "/_action/decrement/{pool}": { "post": { "tags": [ - "Asset Management" + "Increment Storage" ], - "summary": "Upload a media file from URL", - "description": "Creates a new media entity by downloading and uploading a file from the provided URL. This only works if the `shopware.media.enable_url_upload_feature` variable is set to true in the shop environment.", - "operationId": "uploadByUrl", - "requestBody": { - "content": { - "application\\/json": { - "schema": { - "type": "object", - "properties": { - "url": { - "type": "string", - "description": "URL of the file to download and upload" - }, - "id": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "Custom ID for the media entity" - }, - "fileName": { - "type": "string", - "description": "Name of the uploaded file" - }, - "private": { - "type": "boolean", - "description": "Whether the media should be private" - }, - "mediaFolderId": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "ID of the media folder" - }, - "mimeType": { - "type": "string", - "description": "MIME type of the file" - }, - "deduplicate": { - "type": "boolean", - "description": "Whether to deduplicate based on file hash" - } - }, - "required": [ - "url" - ] - } + "summary": "Decrement a value in the specified pool", + "description": "Decrements a value by key in the specified increment pool. This operation decrements the counter for the given key and returns a success response.", + "operationId": "decrementValue", + "parameters": [ + { + "name": "pool", + "in": "path", + "description": "The name of the increment pool.", + "required": true, + "schema": { + "type": "string" } - } - }, - "responses": { - "200": { - "description": "Media file uploaded successfully", - "content": { - "application\\/json": { - "schema": { - "type": "object", - "properties": { - "id": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "ID of the created media entity" - } - } - } - } + }, + { + "name": "cluster", + "in": "query", + "description": "Optional cluster identifier for the decrement operation.", + "required": false, + "schema": { + "type": "string" } } - } - } - }, - "/_action/media/external-link": { - "post": { - "tags": [ - "Asset Management" ], - "summary": "Create external media link", - "description": "Creates a new media entity that links to an external URL without downloading the file.", - "operationId": "externalLink", "requestBody": { + "required": true, "content": { - "application\\/json": { + "application/json": { "schema": { "type": "object", + "required": [ + "key" + ], "properties": { - "url": { - "type": "string", - "description": "URL of the external media file" - }, - "id": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "Custom ID for the media entity" - }, - "fileName": { - "type": "string", - "description": "Name of the file" - }, - "private": { - "type": "boolean", - "description": "Whether the media should be private" - }, - "mediaFolderId": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "ID of the media folder" - }, - "mimeType": { + "key": { "type": "string", - "description": "MIME type of the file" - }, - "deduplicate": { - "type": "boolean", - "description": "Whether to deduplicate based on path" - }, - "thumbnails": { - "type": "array", - "description": "Optional list of external thumbnail URLs for the media entity. Used for CDNs that pre-generated thumbnails alongside the main media file.\nNot to be confused with [remote thumbnails](https://developer.shopware.com/docs/guides/plugins/plugins/content/media/remote-thumbnail-generation.html#remote-thumbnail-generation), which are generated based on a pattern.", - "items": { - "$ref": "#/components/schemas/ExternalThumbnail" - } + "description": "The key to decrement in the pool." } - }, - "required": [ - "url", - "mimeType" - ] + } } } } }, "responses": { "200": { - "description": "External media link created successfully", + "description": "Successfully decremented the value", "content": { - "application\\/json": { + "application/json": { "schema": { "type": "object", "properties": { - "id": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "ID of the created media entity" + "success": { + "type": "boolean", + "example": true } } } } } + }, + "400": { + "description": "Bad request - key parameter missing or cluster parameter missing" } } } }, - "/_action/media/presign-upload": { + "/_action/reset-increment/{pool}": { "post": { "tags": [ - "Asset Management" + "Increment Storage" + ], + "summary": "Reset increment values in pool", + "description": "Resets increment values in the specified pool. Can reset all values or a specific key if provided.", + "operationId": "resetIncrementValues", + "parameters": [ + { + "name": "pool", + "in": "path", + "description": "The name of the increment pool to reset.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "cluster", + "in": "query", + "description": "Cluster identifier for the reset operation.", + "required": true, + "schema": { + "type": "string" + } + } ], - "summary": "Prepare a presigned upload", - "description": "Creates or reuses a media entity and returns a presigned S3 URL for direct browser-to-storage upload. The client uploads the file directly to the returned URL, then calls the finalize endpoint.", - "operationId": "presignUpload", "requestBody": { - "required": true, + "required": false, "content": { "application/json": { "schema": { "type": "object", - "required": [ - "fileName", - "extension", - "mimeType" - ], "properties": { - "fileName": { - "type": "string", - "description": "Name of the file without extension" - }, - "extension": { - "type": "string", - "description": "File extension, e.g. `jpg`, `png`, `pdf`" - }, - "mimeType": { - "type": "string", - "description": "MIME type of the file, e.g. `image/jpeg`" - }, - "mediaFolderId": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "ID of the media folder to place the new media in" - }, - "private": { - "type": "boolean", - "default": false, - "description": "Whether the media should be private" - }, - "mediaId": { + "key": { "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "ID of an existing media entity to replace. If omitted, a new entity is created." + "description": "Optional specific key to reset. If not provided, all values in the pool will be reset." } } } @@ -77112,40 +77364,15 @@ }, "responses": { "200": { - "description": "Presigned upload prepared successfully", + "description": "Successfully reset the increment values", "content": { "application/json": { "schema": { "type": "object", - "required": [ - "mediaId", - "url", - "path", - "expiresAt", - "isDuplicate" - ], "properties": { - "mediaId": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "ID of the media entity" - }, - "url": { - "type": "string", - "description": "Presigned URL to upload the file to via HTTP PUT" - }, - "path": { - "type": "string", - "description": "Storage path of the media file, required for the finalize call" - }, - "expiresAt": { - "type": "string", - "format": "date-time", - "description": "Expiration time of the presigned URL" - }, - "isDuplicate": { + "success": { "type": "boolean", - "description": "Whether a file with the same name already exists" + "example": true } } } @@ -77153,42 +77380,36 @@ } }, "400": { - "description": "Bad request. The file extension is not supported or the file name is invalid.", - "$ref": "#/components/responses/400" - }, - "404": { - "description": "The media entity with the given `mediaId` was not found.", - "$ref": "#/components/responses/404" - }, - "422": { - "description": "Validation error. Required fields (`fileName`, `extension`, `mimeType`) must not be blank.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/failure" - } - } - } + "description": "Bad request - cluster parameter missing" } } } }, - "/_action/media/{mediaId}/finalize-upload": { - "post": { + "/_action/delete-increment/{pool}": { + "delete": { "tags": [ - "Asset Management" + "Increment Storage" ], - "summary": "Finalize a presigned upload", - "description": "Confirms that the file has been uploaded to storage via the presigned URL and updates the media entity with file metadata.", - "operationId": "finalizeUpload", + "summary": "Delete increment keys from pool", + "description": "Deletes specific increment keys from the specified pool.", + "operationId": "deleteIncrementKeys", "parameters": [ { - "name": "mediaId", + "name": "pool", "in": "path", + "description": "The name of the increment pool to delete keys from.", "required": true, - "description": "ID of the media entity to finalize", "schema": { - "$ref": "#/components/schemas/MediaId" + "type": "string" + } + }, + { + "name": "cluster", + "in": "query", + "description": "Cluster identifier for the delete operation.", + "required": true, + "schema": { + "type": "string" } } ], @@ -77199,35 +77420,15 @@ "schema": { "type": "object", "required": [ - "fileName", - "extension", - "mimeType", - "path" + "keys" ], "properties": { - "fileName": { - "type": "string", - "description": "Name of the file without extension" - }, - "extension": { - "type": "string", - "description": "File extension, e.g. `jpg`, `png`, `pdf`" - }, - "mimeType": { - "type": "string", - "description": "MIME type of the file" - }, - "path": { - "type": "string", - "description": "Storage path returned by the presign-upload endpoint" - }, - "width": { - "type": "integer", - "description": "Image width in pixels (optional, for images only)" - }, - "height": { - "type": "integer", - "description": "Image height in pixels (optional, for images only)" + "keys": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Array of keys to delete from the pool." } } } @@ -77235,718 +77436,794 @@ } }, "responses": { - "200": { - "description": "Upload finalized successfully", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "mediaId" - ], - "properties": { - "mediaId": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "ID of the finalized media entity" - } - } - } - } - } + "204": { + "description": "Successfully deleted the increment keys" }, "400": { - "description": "Bad request. The file extension is not supported, the storage path does not match, the file name is already taken, or the file could not be found on the remote storage.", - "$ref": "#/components/responses/400" - }, - "404": { - "description": "The media entity with the given `mediaId` was not found.", - "$ref": "#/components/responses/404" - }, - "422": { - "description": "Validation error. Required fields (`fileName`, `extension`, `mimeType`, `path`) must not be blank.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/failure" - } - } - } + "description": "Bad request - invalid keys parameter or cluster parameter missing" } } } }, - "/_action/media/{mediaId}/external-thumbnails": { + "/_action/order_transaction/{orderTransactionId}/state/{transition}": { "post": { "tags": [ - "Asset Management" + "Order Management" ], - "summary": "Add external thumbnails to media", - "description": "Attaches external thumbnail URLs to an existing external media entity. The media must have an HTTP/HTTPS path (i.e. be an external media link).\n\nUsed for CDNs that pre-generated thumbnails alongside the main media file.\nNot to be confused with [remote thumbnails](https://developer.shopware.com/docs/guides/plugins/plugins/content/media/remote-thumbnail-generation.html#remote-thumbnail-generation), which are generated based on a pattern.\n\nThe thumbnail sized are matched against existing thumbnails sizes and a matching size will automatically be assigned. If there's not existing size, a **new thumbnail size will automatically be created** for each missing size.", - "operationId": "addExternalThumbnails", + "summary": "Transition an order transaction to a new state", + "description": "Changes the order transaction state and informs the customer via email if configured.", + "operationId": "orderTransactionStateTransition", "parameters": [ { - "name": "mediaId", + "name": "orderTransactionId", "in": "path", - "description": "ID of the external media entity the thumbnails will be attached to.", + "description": "Identifier of the order transaction.", "required": true, "schema": { - "$ref": "#/components/schemas/MediaId" + "type": "string", + "pattern": "^[0-9a-f]{32}$" + } + }, + { + "name": "transition", + "in": "path", + "description": "The `action_name` of the `state_machine_transition`. For example `process` if the order state should change from open to in progress.\n\nNote: If you choose a transition that is not available, you will get an error that lists possible transitions for the current state.", + "required": true, + "schema": { + "type": "string" } } ], "requestBody": { - "required": true, + "required": false, "content": { "application/json": { "schema": { - "type": "object", "properties": { - "thumbnails": { + "sendMail": { + "description": "Controls if a mail should be sent to the customer." + }, + "documentIds": { + "description": "A list of document identifiers that should be attached", "type": "array", - "description": "List of external thumbnails to attach", "items": { - "$ref": "#/components/schemas/ExternalThumbnail" + "type": "string", + "pattern": "^[0-9a-f]{32}$" + } + }, + "mediaIds": { + "description": "A list of media identifiers that should be attached", + "type": "array", + "items": { + "type": "string", + "pattern": "^[0-9a-f]{32}$" } + }, + "stateFieldName": { + "description": "This is the state column within the order transaction database table. There should be no need to change it from the default.", + "type": "string", + "default": "stateId" + }, + "internalComment": { + "description": "An optional internal comment that will be saved with the state transition.", + "type": "string" } - } + }, + "type": "object" } } } }, "responses": { - "201": { - "description": "Thumbnails attached successfully", + "200": { + "description": "Returns information about the transition that was made. `#/components/schemas/StateMachineTransition`" + } + } + } + }, + "/_action/container_cache": { + "delete": { + "tags": [ + "System Operations" + ], + "summary": "Clear container caches", + "description": "The container cache is immediately cleared synchronously.", + "operationId": "clearContainerCache", + "responses": { + "204": { + "description": "Returns a no content response indicating that the container cache is cleared." + } + } + } + }, + "/_proxy/generate-imitate-customer-token": { + "post": { + "tags": [ + "Customer impersonation" + ], + "summary": "Generate a customer impersonation token", + "description": "Generates a customer impersonation token for the given customer and sales channel.\n\nThe token can be used to authenticate as the customer in the sales channel.", + "operationId": "generateImitateCustomerToken", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "required": [ + "customerId", + "salesChannelId" + ], + "properties": { + "customerId": { + "description": "ID of the customer", + "type": "string" + }, + "salesChannelId": { + "description": "ID of the sales channel", + "type": "string" + } + }, + "type": "object" + } + } + } + }, + "responses": { + "200": { + "description": "The generated customer impersonation token.", + "content": { + "application/json": { + "schema": { + "properties": { + "token": { + "description": "The generated customer impersonation token", + "type": "string" + } + }, + "type": "object" + } + } + } + } + } + } + }, + "/app-system/privileges/requested": { + "get": { + "tags": [ + "App System" + ], + "summary": "Get requested privileges for all apps", + "description": "Returns the list of requested privileges for all apps. Requires admin scope and `acl_role:read` permission to read.", + "operationId": "getRequestedPrivileges", + "security": [ + { + "oAuth": [ + "admin" + ] + } + ], + "responses": { + "200": { + "description": "A JSON object containing requested privileges.", "content": { "application/json": { "schema": { "type": "object", "properties": { - "mediaId": { - "description": "ID of the media entity the thumbnails were attached to.", - "$ref": "#/components/schemas/MediaId" - }, - "thumbnailsCreated": { - "type": "integer" + "privileges": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + } } } + }, + "example": { + "privileges": { + "SwagAnalytics": [ + "customer:read", + "order:read" + ], + "SwagExample": [ + "product:write" + ] + } } } } }, "400": { - "description": "Media is not an external media entity or path is missing" + "description": "Malformed request." }, - "404": { - "description": "Media entity not found" + "401": { + "description": "Unauthorized Access." + }, + "403": { + "description": "Forbidden. Not a valid integration source." } } - }, - "delete": { + } + }, + "/app-system/{appName}/privileges/accepted": { + "get": { "tags": [ - "Asset Management" + "App System" ], - "summary": "Delete all external thumbnails from media", - "description": "Removes all externally stored thumbnail entries from the given media entity. Only works on external media (media with an HTTP/HTTPS path). Used to replace outdated thumbnails with new ones.", - "operationId": "deleteExternalThumbnails", + "summary": "Get accepted privileges for an app", + "description": "Returns the list of accepted privileges for the current integration. Requires admin scope with an integration.", + "operationId": "getAcceptedPrivileges", "parameters": [ { - "name": "mediaId", + "name": "appName", "in": "path", - "description": "ID of the external media entity the thumbnails will be deleted from..", "required": true, "schema": { - "$ref": "#/components/schemas/MediaId" + "type": "string" } } ], + "security": [ + { + "oAuth": [ + "admin" + ] + } + ], "responses": { "200": { - "description": "Thumbnails deleted successfully", + "description": "A JSON object containing accepted privileges.", "content": { "application/json": { "schema": { "type": "object", "properties": { - "mediaId": { - "description": "ID of the media entity the thumbnails were deleted from.", - "$ref": "#/components/schemas/MediaId" + "privileges": { + "type": "object", + "additionalProperties": { + "type": "boolean" + } } } + }, + "example": { + "privileges": { + "customer:read": true, + "order:read": true + } } } } }, "400": { - "description": "Media is not an external media entity or path is missing" + "description": "Malformed request." + }, + "401": { + "description": "Unauthorized Access." + }, + "403": { + "description": "Forbidden. Not a valid integration source." }, "404": { - "description": "Media entity not found" + "description": "App not found." } } } }, - "/_action/media/{mediaId}/video-cover": { - "post": { + "/app-system/{appName}/privileges": { + "patch": { "tags": [ - "Asset Management" + "App System" ], - "summary": "Assign or remove a video cover image", - "description": "Assigns an image as a cover for a video media entity, or removes the cover if `coverMediaId` is null.", - "operationId": "assignVideoCover", + "summary": "Accept or revoke privileges for an app", + "description": "Accepts or revokes specified privileges for the given app.", + "operationId": "managePrivileges", "parameters": [ { - "name": "mediaId", + "name": "appName", "in": "path", "required": true, - "description": "ID of the video media entity", "schema": { - "$ref": "#/components/schemas/MediaId" + "type": "string" } } ], "requestBody": { + "required": true, "content": { "application/json": { "schema": { "type": "object", "properties": { - "coverMediaId": { - "type": [ - "string", - "null" - ], - "pattern": "^[0-9a-f]{32}$", - "description": "ID of the image media entity to use as cover. Set to null to remove the cover." + "accept": { + "type": "array", + "items": { + "type": "string" + } + }, + "revoke": { + "type": "array", + "items": { + "type": "string" + } } } + }, + "example": { + "accept": [ + "customer:read", + "order:read" + ], + "revoke": [ + "product:write" + ] } } } }, "responses": { "204": { - "description": "Video cover assigned or removed successfully" + "description": "Returns no content if privileges were managed successfully." }, "400": { - "description": "Invalid request" + "description": "Malformed request." + }, + "401": { + "description": "Unauthorized Access." + }, + "403": { + "description": "Forbidden. Not a valid integration source." + }, + "404": { + "description": "App not found." } - } + }, + "security": [ + { + "oAuth": [ + "admin" + ] + } + ] } }, - "/_action/indexing": { + "/_action/app-system/secret/rotate": { "post": { "tags": [ - "System Operations" + "App System" ], - "summary": "Run indexer", - "description": "Runs all registered indexer in the shop asynchronously.", - "operationId": "indexing", + "summary": "Initiate secret rotation for the calling app", + "description": "Initiates an app secret rotation for the calling app. Needs to be called with an integration token belonging to an app. Note that the secret rotation will only be scheduled and then handled asynchronously.", + "operationId": "appSecretRotation", "responses": { - "200": { - "description": "Returns an empty response indicating that the indexing process started." + "202": { + "description": "Returns \"Accepted\" when secret rotation was scheduled." + }, + "400": { + "description": "Malformed request, e.g. when requested with non app integration source." + }, + "401": { + "description": "Unauthorized Access." + }, + "403": { + "description": "Forbidden. Not a valid integration source." + }, + "404": { + "description": "App not found." } - } + }, + "security": [ + { + "oAuth": [ + "admin" + ] + } + ] } }, - "/_action/indexing/{indexer}": { - "post": { + "/app-system/shop/verify": { + "get": { "tags": [ - "System Operations" + "App System", + "Public" ], - "summary": "Iterate an indexer", - "description": "Starts a defined indexer with an offset.\n\nfor the next request. `finish: true` in the response indicates that the indexer is finished", - "operationId": "iterate", + "summary": "Verify a shop's APP_URL", + "description": "Used to verify that a shop's APP_URL points to its self. The passed run ID and token are used to query the cache. It returns 204 no content if the given token can be verified using the run id.", + "operationId": "verifyAppUrl", "parameters": [ { - "name": "indexer", - "in": "path", - "description": "Name of the indexer to iterate.", + "name": "runId", + "in": "query", + "description": "A unique identifier used to look up the token", "required": true, "schema": { - "type": "string", - "pattern": "^[0-9a-f]{32}$" + "type": "string" } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "properties": { - "offset": { - "description": "The offset for the iteration.", - "type": "integer" - } - }, - "type": "object" - } + }, + { + "name": "token", + "in": "query", + "description": "A unique identifier", + "required": true, + "schema": { + "type": "string" } } - }, + ], "responses": { - "200": { - "description": "Returns information about the iteration.", - "content": { - "application/json": { - "schema": { - "properties": { - "finish": { - "description": "Indicates if the indexing process finished.", - "type": "boolean" - }, - "offset": { - "description": "Offset to be used for the next iteration.", - "type": "integer" - } - }, - "type": "object" - } - } - } + "204": { + "description": "An empty response signalling successful verification." + }, + "400": { + "description": "Malformed request or unsuccessful verification." } } } }, - "/_action/state-machine/{entityName}/{entityId}/state": { + "/_action/system-config": { "get": { "tags": [ - "State Machine" + "System Config" ], - "summary": "Get available transitions for an entity", - "description": "Retrieves the available state transitions for the specified entity.", - "operationId": "getEntityState", + "summary": "Get configuration values", + "description": "Returns the configuration values for the given domain and optional sales channel.", + "operationId": "getConfigurationValues", "parameters": [ { - "name": "entityName", - "in": "path", - "description": "Name of the entity.", + "name": "domain", + "in": "query", + "description": "The configuration domain.", "required": true, "schema": { "type": "string" } }, { - "name": "entityId", - "in": "path", - "description": "Identifier of the entity.", - "required": true, + "name": "salesChannelId", + "in": "query", + "description": "The sales channel ID to scope the configuration to.", "schema": { - "type": "string", - "pattern": "^[0-9a-f]{32}$" + "type": "string" } }, { - "name": "stateFieldName", + "name": "inherit", "in": "query", - "description": "This is the state column within the order delivery database table. There should be no need to change it from the default.", - "required": false, + "description": "Whether to include inherited (global) values.", "schema": { - "type": "string", - "default": "stateId" + "type": "boolean", + "default": false } } ], "responses": { "200": { - "description": "Available transitions for the current state.", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "transitions": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "The name of the transition." - }, - "technicalName": { - "type": "string", - "description": "The technical name of the transition." - }, - "actionName": { - "type": "string", - "description": "The action name of the transition." - }, - "fromStateName": { - "type": "string", - "description": "The technical name of the state the transition starts from." - }, - "toStateName": { - "type": "string", - "description": "The technical name of the state the transition goes to." - }, - "url": { - "type": "string", - "description": "The URL to trigger the transition." - } - }, - "required": [ - "name", - "technicalName", - "actionName", - "fromStateName", - "toStateName", - "url" - ] - } - } - }, - "required": [ - "transitions" - ] - } - } - } - }, - "400": { - "description": "Unable to read the entity or entity field." - }, - "403": { - "description": "Forbidden. Missing privileges to access the entity." + "description": "Returns the configuration values as a key-value object." } } - } - }, - "/_action/state-machine/{entityName}/{entityId}/state/{transition}": { + }, "post": { "tags": [ - "State Machine" + "System Config" ], - "summary": "Transition an entity to a new state", - "description": "Changes the entity state by applying the given transition.", - "operationId": "transitionEntityState", + "summary": "Save configuration values", + "description": "Saves the given configuration key-value pairs for the given sales channel.", + "operationId": "saveConfiguration", "parameters": [ { - "name": "entityName", - "in": "path", - "description": "Name of the entity.", - "required": true, + "name": "salesChannelId", + "in": "query", + "description": "The sales channel ID to scope the configuration to.", "schema": { "type": "string" } }, { - "name": "entityId", - "in": "path", - "description": "Identifier of the entity.", - "required": true, + "name": "silent", + "in": "query", + "description": "If true, the HTTP cache will not be invalidated. Use this for internal configuration values that do not affect the storefront.", "schema": { - "type": "string", - "pattern": "^[0-9a-f]{32}$" - } - }, - { - "name": "transition", - "in": "path", - "description": "The `action_name` of the `state_machine_transition`.", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "stateFieldName", - "in": "query", - "description": "This is the state column within the order delivery database table. There should be no need to change it from the default.", - "required": false, - "schema": { - "type": "string", - "default": "stateId" + "type": "boolean", + "default": false } } ], "requestBody": { - "description": "Optional internal comment for the state transition.", + "description": "Key-value pairs of configuration values to save.", + "required": true, "content": { "application/json": { "schema": { "type": "object", - "properties": { - "internalComment": { - "type": "string", - "description": "An optional internal comment that will be saved with the state transition." - } - } + "additionalProperties": true } } } }, "responses": { - "200": { - "description": "State transition applied successfully." - }, - "400": { - "description": "Unable to read the entity or entity field, or invalid transition." - }, - "403": { - "description": "Forbidden. Missing privileges to access the entity." + "204": { + "description": "Configuration saved successfully." } } } }, - "/_action/message-queue/consume": { - "post": { + "/_action/system-config/check": { + "get": { "tags": [ - "System Operations" + "System Config" ], - "summary": "Consume messages from the message queue.", - "description": "This route can be used to consume messages from the message queue. It is intended to be used if\nno cronjob is configured to consume messages regularly.", - "operationId": "consumeMessages", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "required": [ - "receiver" - ], - "properties": { - "receiver": { - "description": "The name of the transport in the messenger that should be processed.\nSee the [Symfony Messenger documentation](https://symfony.com/doc/current/messenger.html) for more information", - "type": "string" - } - }, - "type": "object" - } + "summary": "Check configuration", + "description": "Checks if a configuration domain exists.", + "operationId": "checkConfiguration", + "parameters": [ + { + "name": "domain", + "in": "query", + "description": "The configuration domain to check.", + "required": true, + "schema": { + "type": "string" } } - }, + ], "responses": { "200": { - "description": "Returns information about handled messages", - "content": { - "application/json": { - "schema": { - "properties": { - "handledMessages": { - "description": "The number of messages processed.", - "type": "integer" - } - }, - "type": "object" - } - } - } + "description": "Returns whether the configuration domain exists." } } } }, - "/_action/order_delivery/{orderDeliveryId}/state/{transition}": { - "post": { + "/_action/system-config/schema": { + "get": { "tags": [ - "Order Management" + "System Config" ], - "summary": "Transition an order delivery to a new state", - "description": "Changes the order delivery state and informs the customer via email if configured.", - "operationId": "orderDeliveryStateTransition", + "summary": "Get configuration schema", + "description": "Returns the configuration schema for the given domain.", + "operationId": "getConfiguration", "parameters": [ { - "name": "orderDeliveryId", - "in": "path", - "description": "Identifier of the order delivery.", - "required": true, - "schema": { - "type": "string", - "pattern": "^[0-9a-f]{32}$" - } - }, - { - "name": "transition", - "in": "path", - "description": "The `action_name` of the `state_machine_transition`. For example `process` if the order state should change from open to in progress.\n\nNote: If you choose a transition which is not possible, you will get an error that lists possible transition for the actual state.", + "name": "domain", + "in": "query", + "description": "The configuration domain.", "required": true, "schema": { "type": "string" } } ], - "requestBody": { - "required": false, - "content": { - "application/json": { - "schema": { - "properties": { - "sendMail": { - "description": "Controls if a mail should be send to the customer." - }, - "documentIds": { - "description": "A list of document identifiers that should be attached", - "type": "array", - "items": { - "type": "string", - "pattern": "^[0-9a-f]{32}$" - } - }, - "mediaIds": { - "description": "A list of media identifiers that should be attached", - "type": "array", - "items": { - "type": "string", - "pattern": "^[0-9a-f]{32}$" - } - }, - "stateFieldName": { - "description": "This is the state column within the order delivery database table. There should be no need to change it from the default.", - "type": "string", - "default": "stateId" - }, - "internalComment": { - "description": "An optional internal comment that will be saved with the state transition.", - "type": "string" - } - }, - "type": "object" - } - } - } - }, "responses": { "200": { - "description": "Todo: Use ref of `state_machine_transition` here" + "description": "Returns the configuration schema." } } } }, - "/_action/order/document/download": { + "/_action/system-config/batch": { "post": { "tags": [ - "Document Management" + "System Config" + ], + "summary": "Batch save configuration values", + "description": "Saves configuration values for multiple sales channels at once. The request body is keyed by sales channel ID (use \"null\" for global scope).", + "operationId": "batchSaveConfiguration", + "parameters": [ + { + "name": "silent", + "in": "query", + "description": "If true, the HTTP cache will not be invalidated. Use this for internal configuration values that do not affect the storefront.", + "schema": { + "type": "boolean", + "default": false + } + } ], - "summary": "Download a documents", - "description": "Download a multiple documents in one pdf file.", - "operationId": "downloadDocuments", "requestBody": { - "description": "documentIds", + "description": "Object keyed by sales channel ID, each containing key-value pairs of configuration values.", + "required": true, "content": { "application/json": { "schema": { - "type": "array", - "items": { - "type": "string", - "pattern": "^[0-9a-f]{32}$" + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": true } } } } }, "responses": { - "200": { - "description": "The documents.", - "content": { - "application/octet-stream": { - "schema": { - "type": "string", - "format": "binary" - } - } - } + "204": { + "description": "Configuration saved successfully." } } } }, - "/_action/order/document/{documentTypeName}/create": { - "post": { + "/_info/openapi3.json": { + "get": { "tags": [ - "Document Management" + "System Info & Health Check" ], - "summary": "Create documents for orders", - "description": "Creates documents for orders. Documents can for example be an invoice or a delivery note.", - "operationId": "createDocuments", + "summary": "Get OpenAPI Specification", + "description": "Get information about the admin API in OpenAPI format.", + "operationId": "api-info", "parameters": [ { - "name": "documentTypeName", - "in": "path", - "description": "The type of document to create", - "required": true, + "name": "type", + "in": "query", + "description": "Type of the api", "schema": { - "type": "string" + "type": "string", + "enum": [ + "jsonapi", + "json" + ] } } ], - "requestBody": { - "description": "test", - "required": true, - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "type": "object", - "required": [ - "orderId", - "type" - ], + "responses": { + "200": { + "$ref": "#/components/responses/OpenApi3" + } + } + } + }, + "/_action/cleanup": { + "delete": { + "tags": [ + "System Operations" + ], + "summary": "Clear old cache folders", + "description": "Removes cache folders that are not needed anymore.", + "operationId": "clearOldCacheFolders", + "responses": { + "204": { + "description": "Returns a no content response indicating that the cleanup finished." + } + } + } + }, + "/oauth/sso/config": { + "get": { + "tags": [ + "Authorization & Authentication", + "SSO Login configuration" + ], + "summary": "Loads configuration for the admin login", + "description": "Loads the configuration for the admin login. This configuration is used to load and configure the default or Single Sign On (SSO) login for the admin.", + "operationId": "loadSsoLoginConfig", + "responses": { + "200": { + "description": "Config loaded successfully.", + "content": { + "application/json": { + "schema": { "properties": { - "orderId": { - "description": "Identifier of the order.", - "type": "string", - "pattern": "^[0-9a-f]{32}$" + "useDefault": { + "description": "Experimental: Indicates which login is used. Default or SSO.", + "type": "boolean" }, - "type": { - "description": "Type of the document to be generated.", + "url": { + "description": "Experimental: Contains the return url for the Shopware SSO login.", "type": "string" - }, - "fileType": { - "description": "Type of document file to be generated.", - "type": "string", - "default": "pdf" - }, - "static": { - "description": "Indicate if the document should be static or not.", - "type": "boolean", - "default": false - }, - "referencedDocumentId": { - "description": "Identifier of the reverenced document.", - "type": "string", - "default": "null", - "pattern": "^[0-9a-f]{32}$" - }, - "config": { - "description": "Document specific configuration, like documentNumber, documentDate, documentComment.", - "type": "object" } - } + }, + "type": "object" } } } } - }, + } + } + }, + "/oauth/sso/code": { + "get": { + "tags": [ + "Authorization & Authentication", + "SSO Login callback" + ], + "summary": "Callback function. Fetch an authorization code", + "description": "Fetch an authorization code log in the user.", + "operationId": "callBackWithCode", "responses": { + "302": { + "description": "Experimental: Forwards to the Shopware admin" + }, "200": { - "description": "Documents created successfully. The `api/_action/order/document/create` route can be used to download the document." + "description": "Authorisation process continues", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } } } } }, - "/_action/order/{orderId}/state/{transition}": { + "/oauth/sso/auth": { + "get": { + "tags": [ + "Experimental", + "SSO Login forward" + ], + "summary": "Experimental: Redirect to SSO login", + "description": "Experimental: Creates a redirection to the SSO login page", + "operationId": "ssoAuth", + "responses": { + "302": { + "description": "Experimental: Forwards to SSO login Page" + } + } + } + }, + "/_info/is-sso": { + "get": { + "tags": [ + "Experimental", + "Is SSO environment" + ], + "summary": "Experimental: Is SSO environment", + "description": "Experimental: Returns a boolean which indicates the it is a SSO environment or not", + "operationId": "isSso", + "responses": { + "200": { + "description": "Experimental: Returns if it is a SSO environment or not" + } + } + } + }, + "/_action/sso/invite-user": { "post": { "tags": [ - "Order Management" + "Experimental", + "Invite a new SSO user" ], - "summary": "Transition an order to a new state", - "description": "Changes the order state and informs the customer via email if configured.", - "operationId": "orderStateTransition", + "summary": "Experimental: Invite a new SSO user", + "description": "Experimental: Invite a new SSO user and sends a e-mail with the invite", + "operationId": "inviteUser", + "responses": { + "200": { + "description": "Experimental: Invite a new SSO user and sends a e-mail with the invite" + } + } + } + }, + "/_action/media/{mediaId}/upload": { + "post": { + "tags": [ + "Asset Management" + ], + "summary": "Upload a file to a media entity", + "description": "Adds a new file to a media entity. If the entity has an existing file, it will be replaced.\n\nThe are two methods of providing a file to this route:\n * Use a typical file upload and provide the file in the request\n * Fetch the file from an url. This only works if the `shopware.media.enable_url_upload_feature` variable is set to true in the shop environment.\nTo use file upload via url, the content type has to be `application/json` and the parameter `url` has to be provided.", + "operationId": "upload", "parameters": [ { - "name": "orderId", + "name": "mediaId", "in": "path", - "description": "Identifier of the order.", + "description": "Identifier of the media entity.", "required": true, "schema": { - "type": "string", - "pattern": "^[0-9a-f]{32}$" + "$ref": "#/components/schemas/MediaId" } }, { - "name": "transition", - "in": "path", - "description": "The `action_name` of the `state_machine_transition`. For example `process` if the order state should change from open to in progress.\n\nNote: If you choose a transition that is not available, you will get an error that lists possible transitions for the current state.", + "name": "fileName", + "in": "query", + "description": "Name of the uploaded file. If not provided the media identifier will be used as name", + "schema": { + "type": "string" + } + }, + { + "name": "extension", + "in": "query", + "description": "Extension of the uploaded file. For example `png`", "required": true, "schema": { "type": "string" @@ -77954,37 +78231,21 @@ } ], "requestBody": { - "required": false, "content": { + "application/octet-stream": { + "schema": { + "type": "string", + "format": "binary" + } + }, "application/json": { "schema": { + "required": [ + "url" + ], "properties": { - "sendMail": { - "description": "Controls if a mail should be sent to the customer." - }, - "documentIds": { - "description": "A list of document identifiers that should be attached", - "type": "array", - "items": { - "type": "string", - "pattern": "^[0-9a-f]{32}$" - } - }, - "mediaIds": { - "description": "A list of media identifiers that should be attached", - "type": "array", - "items": { - "type": "string", - "pattern": "^[0-9a-f]{32}$" - } - }, - "stateFieldName": { - "description": "This is the state column within the order database table. There should be no need to change it from the default.", - "type": "string", - "default": "stateId" - }, - "internalComment": { - "description": "An optional internal comment that will be saved with the state transition.", + "url": { + "description": "The url of the media file that will be downloaded.", "type": "string" } }, @@ -77994,124 +78255,87 @@ } }, "responses": { - "200": { - "description": "Todo: Use ref of `state_machine_transition` here" + "204": { + "description": "Media file uploaded successful", + "headers": { + "Location": { + "description": "Contains the url to the uploaded media for a redirect.", + "schema": { + "type": "string" + } + } + } } } } }, - "/_action/sync": { + "/_action/media/upload": { "post": { "tags": [ - "Bulk Operations" - ], - "summary": "Bulk edit entities", - "description": "Starts a sync process for the list of provided actions. This can be upserts and deletes on different entities to an asynchronous process in the background. You can control the behaviour with the `indexing-behavior` header.", - "operationId": "sync", - "parameters": [ - { - "name": "fail-on-error", - "in": "header", - "description": "To continue upcoming actions on errors, set the `fail-on-error` header to `false`.", - "schema": { - "type": "boolean", - "default": true - } - }, - { - "name": "indexing-behavior", - "in": "header", - "description": "Controls the indexing behavior.\n - `disable-indexing`: Data indexing is completely disabled", - "schema": { - "type": "string", - "enum": [ - "use-queue-indexing", - "disable-indexing" - ] - } - } + "Asset Management" ], + "summary": "Upload a new media file", + "description": "Creates a new media entity and uploads a file to it using form-data file upload.", + "operationId": "uploadV2", "requestBody": { - "required": true, "content": { - "application/json": { + "multipart/form-data": { "schema": { - "type": "array", - "items": { - "required": [ - "action", - "entity", - "payload" - ], - "properties": { - "action": { - "description": "The action indicates what should happen with the provided payload.\n * `upsert`: The Sync API does not differ between create and update operations,\n but always performs an upsert operation. During an upsert, the system checks whether the entity already exists in the\n system and updates it if an identifier has been passed, otherwise a new entity is created with this identifier.\n * `delete`: Deletes entities with the provided identifiers", - "type": "string", - "enum": [ - "upsert", - "delete" - ] - }, - "entity": { - "description": "The entity that should be processed with the payload.", - "type": "string", - "example": "product" - }, - "payload": { - "description": "Contains a list of changesets for an entity. If the action type is `delete`,\n a list of identifiers can be provided.", - "type": "array", - "items": { - "type": "object" - } - }, - "criteria": { - "description": "Only for delete operations: Instead of providing IDs in the payload, the filter by which should be deleted can be provided directly.", - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/components/schemas/SimpleFilter" - }, - { - "$ref": "#/components/schemas/EqualsFilter" - }, - { - "$ref": "#/components/schemas/MultiNotFilter" - }, - { - "$ref": "#/components/schemas/RangeFilter" - } - ] - } - } + "type": "object", + "properties": { + "file": { + "type": "string", + "format": "binary", + "description": "The file to upload" }, - "type": "object" - } + "id": { + "type": "string", + "pattern": "^[0-9a-f]{32}$", + "description": "Custom ID for the media entity" + }, + "fileName": { + "type": "string", + "description": "Name of the uploaded file" + }, + "private": { + "type": "boolean", + "description": "Whether the media should be private" + }, + "mediaFolderId": { + "type": "string", + "pattern": "^[0-9a-f]{32}$", + "description": "ID of the media folder" + }, + "mimeType": { + "type": "string", + "description": "MIME type of the file" + }, + "deduplicate": { + "type": "boolean", + "description": "Whether to deduplicate based on file hash" + } + }, + "required": [ + "file" + ] } } } }, "responses": { "200": { - "description": "Returns a sync result containing information about the updated entities", + "description": "Media file uploaded successfully", "content": { - "application/json": { + "application\\/json": { "schema": { + "type": "object", "properties": { - "data": { - "description": "Object with information about updated entities", - "type": "object" - }, - "notFound": { - "description": "Object with information about not found entities", - "type": "object" - }, - "deleted": { - "description": "Object with information about deleted entities", - "type": "object" + "id": { + "type": "string", + "pattern": "^[0-9a-f]{32}$", + "description": "ID of the created media entity" } - }, - "type": "object" + } } } } @@ -78119,660 +78343,590 @@ } } }, - "/_action/order/{orderId}/order-address": { + "/_action/media/upload_by_url": { "post": { "tags": [ - "Order address" - ], - "summary": "Update order addresses", - "description": "Endpoint which takes a list of mapping objects as payload and updates the order addresses accordingly", - "operationId": "updateOrderAddresses", - "parameters": [ - { - "name": "orderId", - "in": "path", - "description": "Identifier of the order.", - "required": true, - "schema": { - "type": "string", - "pattern": "^[0-9a-f]{32}$" - } - } + "Asset Management" ], + "summary": "Upload a media file from URL", + "description": "Creates a new media entity by downloading and uploading a file from the provided URL. This only works if the `shopware.media.enable_url_upload_feature` variable is set to true in the shop environment.", + "operationId": "uploadByUrl", "requestBody": { "content": { - "application/json": { + "application\\/json": { "schema": { "type": "object", "properties": { - "mapping": { - "type": "array", - "items": { - "type": "object", - "properties": { - "customerAddressId": { - "type": "string", - "description": "The ID of the customer address" - }, - "type": { - "type": "string", - "description": "The type of the address" - }, - "deliveryId": { - "description": "The ID of the delivery (optional)", - "oneOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "customerAddressId", - "type" - ] - }, - "description": "The mapping of order addresses" + "url": { + "type": "string", + "description": "URL of the file to download and upload" + }, + "id": { + "type": "string", + "pattern": "^[0-9a-f]{32}$", + "description": "Custom ID for the media entity" + }, + "fileName": { + "type": "string", + "description": "Name of the uploaded file" + }, + "private": { + "type": "boolean", + "description": "Whether the media should be private" + }, + "mediaFolderId": { + "type": "string", + "pattern": "^[0-9a-f]{32}$", + "description": "ID of the media folder" + }, + "mimeType": { + "type": "string", + "description": "MIME type of the file" + }, + "deduplicate": { + "type": "boolean", + "description": "Whether to deduplicate based on file hash" } - } + }, + "required": [ + "url" + ] } } - }, - "required": true + } }, "responses": { - "204": { - "description": "Returns a no content response indicating that the update has been made." + "200": { + "description": "Media file uploaded successfully", + "content": { + "application\\/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "string", + "pattern": "^[0-9a-f]{32}$", + "description": "ID of the created media entity" + } + } + } + } + } } } } }, - "/_action/user/logout": { + "/_action/media/external-link": { "post": { "tags": [ - "Authorization & Authentication" + "Asset Management" ], - "summary": "Logout the current user", - "description": "Revokes all server-side refresh tokens for the currently authenticated administration user and returns a no content response.", - "operationId": "userLogout", + "summary": "Create external media link", + "description": "Creates a new media entity that links to an external URL without downloading the file.", + "operationId": "externalLink", + "requestBody": { + "content": { + "application\\/json": { + "schema": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "URL of the external media file" + }, + "id": { + "type": "string", + "pattern": "^[0-9a-f]{32}$", + "description": "Custom ID for the media entity" + }, + "fileName": { + "type": "string", + "description": "Name of the file" + }, + "private": { + "type": "boolean", + "description": "Whether the media should be private" + }, + "mediaFolderId": { + "type": "string", + "pattern": "^[0-9a-f]{32}$", + "description": "ID of the media folder" + }, + "mimeType": { + "type": "string", + "description": "MIME type of the file" + }, + "deduplicate": { + "type": "boolean", + "description": "Whether to deduplicate based on path" + }, + "thumbnails": { + "type": "array", + "description": "Optional list of external thumbnail URLs for the media entity. Used for CDNs that pre-generated thumbnails alongside the main media file.\nNot to be confused with [remote thumbnails](https://developer.shopware.com/docs/guides/plugins/plugins/content/media/remote-thumbnail-generation.html#remote-thumbnail-generation), which are generated based on a pattern.", + "items": { + "$ref": "#/components/schemas/ExternalThumbnail" + } + } + }, + "required": [ + "url", + "mimeType" + ] + } + } + } + }, "responses": { - "204": { - "description": "Tokens have been revoked successfully." - }, - "401": { - "description": "Unauthorized - the access token is missing or invalid." - }, - "403": { - "description": "The authenticated source does not have a user ID associated." + "200": { + "description": "External media link created successfully", + "content": { + "application\\/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "string", + "pattern": "^[0-9a-f]{32}$", + "description": "ID of the created media entity" + } + } + } + } + } } } } }, - "/oauth/token": { + "/_action/media/presign-upload": { "post": { "tags": [ - "Authorization & Authentication" + "Asset Management" ], - "summary": "Fetch an access token", - "description": "Fetch a access token that can be used to perform authenticated requests. For more information take a look at the [Authentication documentation](https://shopware.stoplight.io/docs/admin-api/docs/concepts/authentication-authorisation.md).", - "operationId": "token", + "summary": "Prepare a presigned upload", + "description": "Creates or reuses a media entity and returns a presigned S3 URL for direct browser-to-storage upload. The client uploads the file directly to the returned URL, then calls the finalize endpoint.", + "operationId": "presignUpload", "requestBody": { "required": true, "content": { "application/json": { "schema": { - "oneOf": [ - { - "$ref": "#/components/schemas/OAuthPasswordGrant" + "type": "object", + "required": [ + "fileName", + "extension", + "mimeType" + ], + "properties": { + "fileName": { + "type": "string", + "description": "Name of the file without extension" }, - { - "$ref": "#/components/schemas/OAuthRefreshTokenGrant" + "extension": { + "type": "string", + "description": "File extension, e.g. `jpg`, `png`, `pdf`" }, - { - "$ref": "#/components/schemas/OAuthClientCredentialsGrant" + "mimeType": { + "type": "string", + "description": "MIME type of the file, e.g. `image/jpeg`" + }, + "mediaFolderId": { + "type": "string", + "pattern": "^[0-9a-f]{32}$", + "description": "ID of the media folder to place the new media in" + }, + "private": { + "type": "boolean", + "default": false, + "description": "Whether the media should be private" + }, + "mediaId": { + "type": "string", + "pattern": "^[0-9a-f]{32}$", + "description": "ID of an existing media entity to replace. If omitted, a new entity is created." } - ] + } } } } }, "responses": { "200": { - "description": "Authorized successfully.", + "description": "Presigned upload prepared successfully", "content": { "application/json": { "schema": { + "type": "object", "required": [ - "token_type", - "expires_in", - "access_token" + "mediaId", + "url", + "path", + "expiresAt", + "isDuplicate" ], "properties": { - "token_type": { - "description": "Type of the token.", - "type": "string" + "mediaId": { + "type": "string", + "pattern": "^[0-9a-f]{32}$", + "description": "ID of the media entity" }, - "expires_in": { - "description": "Token lifetime in seconds.", - "type": "integer" + "url": { + "type": "string", + "description": "Presigned URL to upload the file to via HTTP PUT" }, - "access_token": { - "description": "The access token that can be used for subsequent requests", - "type": "string" + "path": { + "type": "string", + "description": "Storage path of the media file, required for the finalize call" }, - "refresh_token": { - "description": "The refresh token that can be used to refresh the access token. This field is not returned on grant type `refresh_token`.", - "type": "string" + "expiresAt": { + "type": "string", + "format": "date-time", + "description": "Expiration time of the presigned URL" + }, + "isDuplicate": { + "type": "boolean", + "description": "Whether a file with the same name already exists" } - }, - "type": "object" + } } } } }, "400": { + "description": "Bad request. The file extension is not supported or the file name is invalid.", "$ref": "#/components/responses/400" + }, + "404": { + "description": "The media entity with the given `mediaId` was not found.", + "$ref": "#/components/responses/404" + }, + "422": { + "description": "Validation error. Required fields (`fileName`, `extension`, `mimeType`) must not be blank.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/failure" + } + } + } } } } }, - "/oauth/sso/config": { - "get": { + "/_action/media/{mediaId}/finalize-upload": { + "post": { "tags": [ - "Experimental", - "SSO Login configuration" + "Asset Management" + ], + "summary": "Finalize a presigned upload", + "description": "Confirms that the file has been uploaded to storage via the presigned URL and updates the media entity with file metadata.", + "operationId": "finalizeUpload", + "parameters": [ + { + "name": "mediaId", + "in": "path", + "required": true, + "description": "ID of the media entity to finalize", + "schema": { + "$ref": "#/components/schemas/MediaId" + } + } ], - "summary": "Experimental: Loads SSO login configuration.", - "description": "Experimental: Loads the SSO login configuration to configure the forward to the Shopware SSO login page.", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "fileName", + "extension", + "mimeType", + "path" + ], + "properties": { + "fileName": { + "type": "string", + "description": "Name of the file without extension" + }, + "extension": { + "type": "string", + "description": "File extension, e.g. `jpg`, `png`, `pdf`" + }, + "mimeType": { + "type": "string", + "description": "MIME type of the file" + }, + "path": { + "type": "string", + "description": "Storage path returned by the presign-upload endpoint" + }, + "width": { + "type": "integer", + "description": "Image width in pixels (optional, for images only)" + }, + "height": { + "type": "integer", + "description": "Image height in pixels (optional, for images only)" + } + } + } + } + } + }, "responses": { "200": { - "description": "Experimental: Returns the configuration for the SSO login page forward.", + "description": "Upload finalized successfully", "content": { "application/json": { "schema": { "type": "object", + "required": [ + "mediaId" + ], "properties": { - "useDefault": { - "description": "Experimental: Indicates which login is used. Default or SSO.", - "type": "boolean" - }, - "url": { - "description": "Experimental: Contains the return url for the Shopware SSO login.", - "type": "string" + "mediaId": { + "type": "string", + "pattern": "^[0-9a-f]{32}$", + "description": "ID of the finalized media entity" } } } } } - } - }, - "operationId": "loadSsoLoginConfig" - } - }, - "/oauth/sso/code": { - "get": { - "tags": [ - "Experimental", - "SSO Login callback" - ], - "summary": "Experimental: Callback for SSO login", - "description": "Experimental: Logs in the user into the Shopware shop and forwards to the admin", - "responses": { - "200": { - "description": "Authorisation process continues", + }, + "400": { + "description": "Bad request. The file extension is not supported, the storage path does not match, the file name is already taken, or the file could not be found on the remote storage.", + "$ref": "#/components/responses/400" + }, + "404": { + "description": "The media entity with the given `mediaId` was not found.", + "$ref": "#/components/responses/404" + }, + "422": { + "description": "Validation error. Required fields (`fileName`, `extension`, `mimeType`, `path`) must not be blank.", "content": { "application/json": { "schema": { - "type": "object" + "$ref": "#/components/schemas/failure" } } } - }, - "302": { - "description": "Experimental: Forwards to the Shopware admin" } - }, - "operationId": "callBackWithCode" + } } }, - "/_action/scheduled-task/run": { + "/_action/media/{mediaId}/external-thumbnails": { "post": { "tags": [ - "System Operations" + "Asset Management" ], - "summary": "Run scheduled tasks.", - "description": "Starts the scheduled task worker to handle the next scheduled tasks.", - "operationId": "runScheduledTasks", - "responses": { - "200": { - "description": "Returns a success message indicating a successful run.", - "content": { - "application/json": { - "schema": { - "properties": { - "message": { - "description": "Success message", - "type": "string" - } - }, - "type": "object" - } - } - } - } - } - } - }, - "/_action/scheduled-task/min-run-interval": { - "get": { - "tags": [ - "System Operations" - ], - "summary": "Get the minimum schedules task interval", - "description": "Fetches the smallest interval that a scheduled task uses.", - "operationId": "getMinRunInterval", - "responses": { - "200": { - "description": "Returns the minimum interval.", - "content": { - "application/json": { - "schema": { - "properties": { - "minRunInterval": { - "description": "Minimal interval in seconds.", - "type": "string" - } - }, - "type": "object" - } - } - } - } - } - } - }, - "/_action/order_transaction/{orderTransactionId}/state/{transition}": { - "post": { - "tags": [ - "Order Management" - ], - "summary": "Transition an order transaction to a new state", - "description": "Changes the order transaction state and informs the customer via email if configured.", - "operationId": "orderTransactionStateTransition", + "summary": "Add external thumbnails to media", + "description": "Attaches external thumbnail URLs to an existing external media entity. The media must have an HTTP/HTTPS path (i.e. be an external media link).\n\nUsed for CDNs that pre-generated thumbnails alongside the main media file.\nNot to be confused with [remote thumbnails](https://developer.shopware.com/docs/guides/plugins/plugins/content/media/remote-thumbnail-generation.html#remote-thumbnail-generation), which are generated based on a pattern.\n\nThe thumbnail sized are matched against existing thumbnails sizes and a matching size will automatically be assigned. If there's not existing size, a **new thumbnail size will automatically be created** for each missing size.", + "operationId": "addExternalThumbnails", "parameters": [ { - "name": "orderTransactionId", - "in": "path", - "description": "Identifier of the order transaction.", - "required": true, - "schema": { - "type": "string", - "pattern": "^[0-9a-f]{32}$" - } - }, - { - "name": "transition", + "name": "mediaId", "in": "path", - "description": "The `action_name` of the `state_machine_transition`. For example `process` if the order state should change from open to in progress.\n\nNote: If you choose a transition that is not available, you will get an error that lists possible transitions for the current state.", + "description": "ID of the external media entity the thumbnails will be attached to.", "required": true, "schema": { - "type": "string" + "$ref": "#/components/schemas/MediaId" } } ], "requestBody": { - "required": false, + "required": true, "content": { "application/json": { "schema": { + "type": "object", "properties": { - "sendMail": { - "description": "Controls if a mail should be sent to the customer." - }, - "documentIds": { - "description": "A list of document identifiers that should be attached", - "type": "array", - "items": { - "type": "string", - "pattern": "^[0-9a-f]{32}$" - } - }, - "mediaIds": { - "description": "A list of media identifiers that should be attached", + "thumbnails": { "type": "array", + "description": "List of external thumbnails to attach", "items": { - "type": "string", - "pattern": "^[0-9a-f]{32}$" + "$ref": "#/components/schemas/ExternalThumbnail" } - }, - "stateFieldName": { - "description": "This is the state column within the order transaction database table. There should be no need to change it from the default.", - "type": "string", - "default": "stateId" - }, - "internalComment": { - "description": "An optional internal comment that will be saved with the state transition.", - "type": "string" } - }, - "type": "object" + } } } } }, "responses": { - "200": { - "description": "Returns information about the transition that was made. `#/components/schemas/StateMachineTransition`" + "201": { + "description": "Thumbnails attached successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "mediaId": { + "description": "ID of the media entity the thumbnails were attached to.", + "$ref": "#/components/schemas/MediaId" + }, + "thumbnailsCreated": { + "type": "integer" + } + } + } + } + } + }, + "400": { + "description": "Media is not an external media entity or path is missing" + }, + "404": { + "description": "Media entity not found" } } - } - }, - "/_info/openapi3.json": { - "get": { + }, + "delete": { "tags": [ - "System Info & Health Check" + "Asset Management" ], - "summary": "Get OpenAPI Specification", - "description": "Get information about the admin API in OpenAPI format.", - "operationId": "api-info", + "summary": "Delete all external thumbnails from media", + "description": "Removes all externally stored thumbnail entries from the given media entity. Only works on external media (media with an HTTP/HTTPS path). Used to replace outdated thumbnails with new ones.", + "operationId": "deleteExternalThumbnails", "parameters": [ { - "name": "type", - "in": "query", - "description": "Type of the api", + "name": "mediaId", + "in": "path", + "description": "ID of the external media entity the thumbnails will be deleted from..", + "required": true, "schema": { - "type": "string", - "enum": [ - "jsonapi", - "json" - ] + "$ref": "#/components/schemas/MediaId" } } ], "responses": { "200": { - "$ref": "#/components/responses/OpenApi3" + "description": "Thumbnails deleted successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "mediaId": { + "description": "ID of the media entity the thumbnails were deleted from.", + "$ref": "#/components/schemas/MediaId" + } + } + } + } + } + }, + "400": { + "description": "Media is not an external media entity or path is missing" + }, + "404": { + "description": "Media entity not found" } } } }, - "/_action/order_transaction_capture_refund/{refundId}": { + "/_action/media/{mediaId}/video-cover": { "post": { "tags": [ - "Order Management" + "Asset Management" ], - "summary": "Refund an order transaction capture", - "description": "Refunds an order transaction capture.", - "operationId": "orderTransactionCaptureRefund", + "summary": "Assign or remove a video cover image", + "description": "Assigns an image as a cover for a video media entity, or removes the cover if `coverMediaId` is null.", + "operationId": "assignVideoCover", "parameters": [ { - "name": "refundId", + "name": "mediaId", "in": "path", - "description": "Identifier of the order transaction capture refund.", "required": true, + "description": "ID of the video media entity", "schema": { - "type": "string", - "pattern": "^[0-9a-f]{32}$" + "$ref": "#/components/schemas/MediaId" } } ], - "responses": { - "204": { - "description": "Refund was successful" - }, - "400": { - "description": "Something went wrong, while processing the refund" - }, - "404": { - "description": "Refund with id not found" - } - } - } - }, - "/_action/cleanup": { - "delete": { - "tags": [ - "System Operations" - ], - "summary": "Clear old cache folders", - "description": "Removes cache folders that are not needed anymore.", - "operationId": "clearOldCacheFolders", - "responses": { - "204": { - "description": "Returns a no content response indicating that the cleanup finished." - } - } - } - }, - "/_action/index": { - "post": { - "tags": [ - "System Operations" - ], - "summary": "Run indexer", - "description": "Runs all registered indexer in the shop asynchronously.", - "operationId": "index", "requestBody": { "content": { "application/json": { "schema": { + "type": "object", "properties": { - "skip": { - "description": "Array of indexers/updaters to be skipped.", - "type": "array", - "items": { - "type": "string" - } + "coverMediaId": { + "type": [ + "string", + "null" + ], + "pattern": "^[0-9a-f]{32}$", + "description": "ID of the image media entity to use as cover. Set to null to remove the cover." } - }, - "type": "object" + } } } } }, "responses": { "204": { - "description": "Returns a no content response indicating that the indexing progress startet." - } - } - } - }, - "/_action/cache": { - "delete": { - "tags": [ - "System Operations" - ], - "summary": "Clear caches", - "description": "The cache is immediately cleared synchronously for all used adapters.", - "operationId": "clearCache", - "responses": { - "204": { - "description": "Returns a no content response indicating that the cache has been cleared." - } - } - } - }, - "/_action/cache-delayed": { - "delete": { - "tags": [ - "System Operations" - ], - "summary": "Clear all invalidated caches", - "description": "Directly triggers invalidation of all cache tags that were marked for invalidation.", - "operationId": "clearCacheDelayed", - "parameters": [ - { - "name": "refreshOpenSearch", - "in": "query", - "required": false, - "description": "This parameter indicates that in addition to invalidating the delayed caches, the opensearch indices will also be refreshed, which should lead to a clean state on the next read requests. When OpenSearch is not used this parameter will be ignored.", - "schema": { - "type": "boolean", - "default": false - } - } - ], - "responses": { - "204": { - "description": "Returns a no content response indicating that the cache has been cleared." - } - } - } - }, - "/oauth/sso/auth": { - "get": { - "tags": [ - "Experimental", - "SSO Login forward" - ], - "summary": "Experimental: Redirect to SSO login", - "description": "Experimental: Creates a redirection to the SSO login page", - "operationId": "ssoAuth", - "responses": { - "302": { - "description": "Experimental: Forwards to SSO login Page" - } - } - } - }, - "/_info/is-sso": { - "get": { - "tags": [ - "Experimental", - "Is SSO environment" - ], - "summary": "Experimental: Is SSO environment", - "description": "Experimental: Returns a boolean which indicates the it is a SSO environment or not", - "operationId": "isSso", - "responses": { - "200": { - "description": "Experimental: Returns if it is a SSO environment or not" + "description": "Video cover assigned or removed successfully" + }, + "400": { + "description": "Invalid request" } } } }, - "/_action/sso/invite-user": { + "/oauth/token": { "post": { "tags": [ - "Experimental", - "Invite a new SSO user" - ], - "summary": "Experimental: Invite a new SSO user", - "description": "Experimental: Invite a new SSO user and sends a e-mail with the invite", - "operationId": "inviteUser", - "responses": { - "200": { - "description": "Experimental: Invite a new SSO user and sends a e-mail with the invite" - } - } - } - }, - "/_action/cache_info": { - "get": { - "tags": [ - "System Operations" + "Authorization & Authentication" ], - "summary": "Get cache information", - "description": "Get information about the cache configuration", - "operationId": "info", - "responses": { - "200": { - "description": "Information about the cache state.", - "content": { - "application/json": { - "schema": { - "properties": { - "environment": { - "description": "The active environment.", - "type": "string" - }, - "httpCache": { - "description": "State of the HTTP cache.", - "type": "boolean" - }, - "cacheAdapter": { - "description": "The active cache adapter.", - "type": "string" - } + "summary": "Fetch an access token", + "description": "Fetch a access token that can be used to perform authenticated requests. For more information take a look at the [Authentication documentation](https://shopware.stoplight.io/docs/admin-api/docs/concepts/authentication-authorisation.md).", + "operationId": "token", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "oneOf": [ + { + "$ref": "#/components/schemas/OAuthPasswordGrant" }, - "type": "object" - } - } - } - } - } - } - }, - "/_info/queue.json": { - "get": { - "tags": [ - "System Info & Health Check" - ], - "summary": "Get message queue statistics (deprecated)", - "description": "Returns increment-based message queue statistics.\n\n**Deprecated:** This endpoint is deprecated and will be removed in v6.8.0. Use `GET /_info/message-stats.json` instead for accurate message processing statistics.", - "operationId": "queue", - "deprecated": true, - "responses": { - "200": { - "description": "Message queue statistics returned.", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Fully qualified class name of the message." - }, - "size": { - "type": "integer", - "description": "Number of pending messages of this type." - } - }, - "required": [ - "name", - "size" - ] - } - }, - "example": [ { - "name": "Shopware\\Core\\Content\\Product\\DataAbstractionLayer\\ProductIndexingMessage", - "size": 150 + "$ref": "#/components/schemas/OAuthRefreshTokenGrant" }, { - "name": "Shopware\\Core\\Content\\Media\\Message\\GenerateThumbnailsMessage", - "size": 25 + "$ref": "#/components/schemas/OAuthClientCredentialsGrant" } ] } } } - } - } - }, - "/_info/version": { - "get": { - "tags": [ - "System Info & Health Check" - ], - "summary": "Get the Shopware version", - "description": "Get the version of the Shopware instance", - "operationId": "infoShopwareVersion", + }, "responses": { "200": { - "description": "Returns the version of the Shopware instance.", + "description": "Authorized successfully.", "content": { "application/json": { "schema": { + "required": [ + "token_type", + "expires_in", + "access_token" + ], "properties": { - "version": { - "description": "The Shopware version.", + "token_type": { + "description": "Type of the token.", + "type": "string" + }, + "expires_in": { + "description": "Token lifetime in seconds.", + "type": "integer" + }, + "access_token": { + "description": "The access token that can be used for subsequent requests", + "type": "string" + }, + "refresh_token": { + "description": "The refresh token that can be used to refresh the access token. This field is not returned on grant type `refresh_token`.", "type": "string" } }, @@ -78780,50 +78934,9 @@ } } } - } - } - } - }, - "/_info/flow-actions.json": { - "get": { - "tags": [ - "System Info & Health Check" - ], - "summary": "Get actions for flow builder", - "description": "Get a list of action for flow builder.", - "operationId": "flow-actions", - "responses": { - "200": { - "description": "Returns a list of action for flow builder.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/flowBuilderActionsResponse" - } - } - } - } - } - } - }, - "/_info/events.json": { - "get": { - "tags": [ - "System Info & Health Check" - ], - "summary": "Get Business events", - "description": "Get a list of about the business events.", - "operationId": "business-events", - "responses": { - "200": { - "description": "Returns a list of about the business events.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/businessEventsResponse" - } - } - } + }, + "400": { + "$ref": "#/components/responses/400" } } } @@ -78875,360 +78988,1144 @@ } } }, - "/_info/health-check": { - "get": { + "/_action/message-queue/consume": { + "post": { "tags": [ - "System Info & Health Check" + "System Operations" ], - "summary": "Check that the Application is running", - "operationId": "healthCheck", + "summary": "Consume messages from the message queue.", + "description": "This route can be used to consume messages from the message queue. It is intended to be used if\nno cronjob is configured to consume messages regularly.", + "operationId": "consumeMessages", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "required": [ + "receiver" + ], + "properties": { + "receiver": { + "description": "The name of the transport in the messenger that should be processed.\nSee the [Symfony Messenger documentation](https://symfony.com/doc/current/messenger.html) for more information", + "type": "string" + } + }, + "type": "object" + } + } + } + }, "responses": { "200": { - "description": "Returns empty response" - }, - "500": { - "description": "Application is not working properly" + "description": "Returns information about handled messages", + "content": { + "application/json": { + "schema": { + "properties": { + "handledMessages": { + "description": "The number of messages processed.", + "type": "integer" + } + }, + "type": "object" + } + } + } } } } }, - "/_info/system-health-check": { - "get": { + "/_action/mail-template/send": { + "post": { "tags": [ - "System Info & Health Check" + "Mail Operations" ], - "summary": "Perform a detailed system health check", - "operationId": "systemHealthCheck", - "parameters": [ - { - "name": "verbose", - "in": "query", - "required": false, - "schema": { - "type": "boolean", - "default": false - }, - "description": "Include detailed information in the response" + "summary": "Send a mail", + "description": "Generates a mail and sends it to the customer. The mail content is rendered with data passed through the request.\n\nTake a look at the `salesChannel` entity for possible values. For example `{{ salesChannel.name }}` can be used.", + "operationId": "send", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "required": [ + "recipients", + "salesChannelId", + "contentHtml", + "contentPlain", + "subject" + ], + "properties": { + "recipients": { + "description": "A map of recipients with name and mail address.", + "type": "object", + "example": { + "test1@example.com": "Test user 1", + "test2@example.com": "Test user 2" + }, + "additionalProperties": { + "description": "Name of the recipient. Can be null to omit the display name.", + "type": [ + "string", + "null" + ] + } + }, + "salesChannelId": { + "description": "Identifier of the sales channel from which the mail should be send.", + "type": "string", + "pattern": "^[0-9a-f]{32}$" + }, + "contentHtml": { + "description": "The content of the mail in HTML format.", + "type": "string" + }, + "contentPlain": { + "description": "The content of the mail as plain text.", + "type": "string" + }, + "subject": { + "description": "Subject of the mail.", + "type": "string" + }, + "senderName": { + "description": "Name of the sender.", + "type": "string" + }, + "senderEmail": { + "description": "Mail address of the sender. If not set, `core.basicInformation.email` or `core.mailerSettings.senderAddress` will be used from the shop configuration.", + "type": "string", + "format": "email" + }, + "mediaIds": { + "description": "List of media identifiers which should be attached to the mail.", + "type": "array", + "items": { + "type": "string", + "pattern": "^[0-9a-f]{32}$" + } + }, + "documentIds": { + "description": "List of document identifiers which should be attached to the mail.", + "type": "array", + "items": { + "type": "string", + "pattern": "^[0-9a-f]{32}$" + } + }, + "binAttachments": { + "description": "A list of binary attachments which should be added to the mail.", + "type": "array", + "items": { + "required": [ + "content", + "fileName", + "mimeType" + ], + "properties": { + "content": { + "description": "Binary content of the attachment.", + "type": "string" + }, + "fileName": { + "description": "File name of the attachment.", + "type": "string" + }, + "mimeType": { + "description": "Mime type of the attachment.", + "type": "string" + } + }, + "type": "object" + } + }, + "recipientsBcc": { + "description": "A mail address or a map of recipients with name and mail address to be set in BCC.", + "oneOf": [ + { + "type": "string", + "format": "email" + }, + { + "type": "object", + "example": { + "test1@example.com": "Test user 1", + "test2@example.com": "Test user 2" + }, + "additionalProperties": { + "description": "Name of the recipient. Can be null to omit the display name.", + "type": [ + "string", + "null" + ] + } + } + ] + }, + "recipientsCc": { + "description": "A mail address or a map of recipients with name and mail address to be set in CC.", + "oneOf": [ + { + "type": "string", + "format": "email" + }, + { + "type": "object", + "example": { + "test1@example.com": "Test user 1", + "test2@example.com": "Test user 2" + }, + "additionalProperties": { + "description": "Name of the recipient. Can be null to omit the display name.", + "type": [ + "string", + "null" + ] + } + } + ] + }, + "replyTo": { + "description": "A mail address or a map of mail addresses with name to be set in reply-to.", + "oneOf": [ + { + "type": "string", + "format": "email" + }, + { + "type": "object", + "example": { + "test1@example.com": "Test user 1", + "test2@example.com": "Test user 2" + }, + "additionalProperties": { + "description": "Name of the recipient. Can be null to omit the display name.", + "type": [ + "string", + "null" + ] + } + } + ] + }, + "returnPath": { + "description": "A mail address or a map of mail addresses with name to be set in return-path.", + "oneOf": [ + { + "type": "string", + "format": "email" + }, + { + "type": "object", + "example": { + "test1@example.com": "Test user 1", + "test2@example.com": "Test user 2" + }, + "additionalProperties": { + "description": "Name of the recipient. Can be null to omit the display name.", + "type": [ + "string", + "null" + ] + } + } + ] + }, + "mailTemplateId": { + "description": "Identifier of the mail template that should be used for attachments and sender defaults.", + "type": "string", + "pattern": "^[0-9a-f]{32}$" + }, + "mailTemplateData": { + "description": "A map of available data that is used to fill the mail template. Values in this map override generated or entity-derived template data with the same top-level keys.", + "type": "object", + "additionalProperties": true, + "example": { + "salesChannel": { + "name": "Storefront" + } + } + }, + "testMode": { + "description": "Enables mail test mode. The mail is still sent, but template rendering runs with the renderer's test mode enabled, a fallback `order.deepLinkCode` of `home` is injected when missing, and debug headers such as `X-Shopware-Language-Id` plus available event or sales-channel headers are added to the message.", + "type": "boolean" + } + }, + "type": "object" + } + } } - ], + }, "responses": { "200": { - "description": "Returns the system health check results", + "description": "The mail was sent successful", "content": { "application/json": { "schema": { - "type": "object", + "required": [ + "size" + ], "properties": { - "checks": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "healthy": { - "type": "boolean" - }, - "status": { - "type": "string" - }, - "message": { - "type": "string" - }, - "extra": { - "type": "array", - "items": { - "type": "object", - "additionalProperties": true - } - } - } - } + "size": { + "description": "Length of the email message", + "type": "integer" } - } + }, + "type": "object" } } } }, - "500": { - "description": "Application is not working properly" + "400": { + "description": "Invalid request data", + "$ref": "#/components/responses/400" } } } }, - "/_action/index-products": { + "/_action/mail-template/validate": { "post": { "tags": [ - "System Operations" + "Mail Operations" ], - "summary": "Send product indexing message", - "description": "Dispatches a product indexing message to the message bus, with the provided ids", - "operationId": "productIndexing", + "summary": "Validate a mail content", + "description": "Validates if content for a mail can be rendered without sending an email.", + "operationId": "validate", + "deprecated": true, + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "required": [ + "contentHtml", + "contentPlain" + ], + "properties": { + "contentHtml": { + "description": "The content of the mail in HTML format.", + "type": "string" + }, + "contentPlain": { + "description": "The content of the mail as plain text.", + "type": "string" + } + }, + "type": "object" + } + } + } + }, "responses": { "204": { - "description": "Returns an empty response indicating that the message dispatched." + "description": "Returns a no content response indicating the mail content was rendered successfully." } } } }, - "/_action/increment/{pool}": { + "/_action/mail-template/build": { "post": { "tags": [ - "Increment Storage" + "Mail Operations" ], - "summary": "Increment a value in the specified pool", - "description": "Increments a value by key in the specified increment pool. This operation increments the counter for the given key and returns a success response.", - "operationId": "incrementValue", - "parameters": [ - { - "name": "pool", - "in": "path", - "description": "The name of the increment pool (e.g., 'user_activity', 'message_queue').", - "required": true, - "schema": { - "type": "string" + "summary": "Build up a mail template", + "description": "Generates a preview of a mail template when all the required data is passed through the request.", + "operationId": "build", + "deprecated": true, + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "required": [ + "mailTemplateType", + "mailTemplate" + ], + "properties": { + "mailTemplateType": { + "description": "Only the property `templateData` is used. It provides additional variables to the templating engine.", + "properties": { + "templateData": { + "description": "An associative array that is handed over to the templating engine and can be used as variables in the mail content.", + "type": "object", + "example": { + "order": { + "orderNumber": 5000, + "customerName": "Example Customer" + }, + "messageOfTheDay": "An apple a day keeps the doctor away!" + }, + "additionalProperties": true + } + }, + "type": "object" + }, + "mailTemplate": { + "description": "The content of the mail as plain text.", + "properties": { + "contentHtml": { + "description": "The content of the mail template in html format.", + "type": "string", + "example": "Hello {{ order.customerName }}, this is example mail content, the current date is {{ 'now'|date('d/m/Y') }}" + } + }, + "type": "object" + } + }, + "type": "object" + } + } + } + }, + "responses": { + "200": { + "description": "The rendered simulation result of the mail template parts.", + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + } + } + }, + "/_action/mail-template/simulate": { + "post": { + "tags": [ + "Mail Operations" + ], + "summary": "Simulate a mail template", + "description": "Generates simulated data for a given event name and renders the provided mail template content against it.", + "operationId": "simulateMailTemplate", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "required": [ + "templateParts", + "eventName" + ], + "properties": { + "templateParts": { + "description": "A map of mail template fields and their template content to render.", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "example": { + "subject": "Order {{ order.orderNumber }} confirmation", + "senderName": "{{ salesChannel.name }}", + "contentHtml": "