Add images via Shopware 6 API

Viewed 5619

I have a Shopware 6.3 shop and need to migrate images to it using the integration API.

How should I construct a body for a media upload? Do I need to put a file somewhere or just pass in the link?

I have managed to push new products into Shopware via guide here: https://docs.shopware.com/en/shopware-platform-dev-en/admin-api-guide/writing-entities?category=shopware-platform-dev-en/admin-api-guide#creating-entities but I am not sure how to handle media. In this guide it is only explained how to create links between already uploaded media files to products in here https://docs.shopware.com/en/shopware-platform-dev-en/admin-api-guide/writing-entities?category=shopware-platform-dev-en/admin-api-guide#media-handling but no examples as to how to actually push the media files.

I have URL's for each image I need (in the database, along with produc id's and image positions).

The entity schema describes media as:

    "media": {
        "name": "media",
        "translatable": [
            "alt",
            "title",
            "customFields"
        ],
        "properties": {
            "id": {
                "type": "string",
                "format": "uuid"
            },
            "userId": {
                "type": "string",
                "format": "uuid"
            },
            "mediaFolderId": {
                "type": "string",
                "format": "uuid"
            },
            "mimeType": {
                "type": "string",
                "readOnly": true
            },
            "fileExtension": {
                "type": "string",
                "readOnly": true
            },
            "uploadedAt": {
                "type": "string",
                "format": "date-time",
                "readOnly": true
            },
            "fileName": {
                "type": "string",
                "readOnly": true
            },
            "fileSize": {
                "type": "integer",
                "format": "int64",
                "readOnly": true
            },
            "metaData": {
                "type": "object",
                "readOnly": true
            },
            "mediaType": {
                "type": "object",
                "readOnly": true
            },
            "alt": {
                "type": "string"
            },
            "title": {
                "type": "string"
            },
            "url": {
                "type": "string"
            },
            "hasFile": {
                "type": "boolean"
            },
            "private": {
                "type": "boolean"
            },
            "customFields": {
                "type": "object"
            },
            "createdAt": {
                "type": "string",
                "format": "date-time",
                "readOnly": true
            },
            "updatedAt": {
                "type": "string",
                "format": "date-time",
                "readOnly": true
            },
            "translated": {
                "type": "object"
            },
            "tags": {
                "type": "array",
                "entity": "tag"
            },
            "thumbnails": {
                "type": "array",
                "entity": "media_thumbnail"
            },
            "user": {
                "type": "object",
                "entity": "user"
            },
            "categories": {
                "type": "array",
                "entity": "category"
            },
            "productManufacturers": {
                "type": "array",
                "entity": "product_manufacturer"
            },
            "productMedia": {
                "type": "array",
                "entity": "product_media"
            },
            "avatarUser": {
                "type": "object",
                "entity": "user"
            },
            "mediaFolder": {
                "type": "object",
                "entity": "media_folder"
            },
            "propertyGroupOptions": {
                "type": "array",
                "entity": "property_group_option"
            },
            "mailTemplateMedia": {
                "type": "array",
                "entity": "mail_template_media"
            },
            "documentBaseConfigs": {
                "type": "array",
                "entity": "document_base_config"
            },
            "shippingMethods": {
                "type": "array",
                "entity": "shipping_method"
            },
            "paymentMethods": {
                "type": "array",
                "entity": "payment_method"
            },
            "productConfiguratorSettings": {
                "type": "array",
                "entity": "product_configurator_setting"
            },
            "orderLineItems": {
                "type": "array",
                "entity": "order_line_item"
            },
            "cmsBlocks": {
                "type": "array",
                "entity": "cms_block"
            },
            "cmsSections": {
                "type": "array",
                "entity": "cms_section"
            },
            "cmsPages": {
                "type": "array",
                "entity": "cms_page"
            },
            "documents": {
                "type": "array",
                "entity": "document"
            }
        }
    },

but it is not clear what fields are crucial. Do I need to create product-media folder first and then use it's id when making a POST request to media endpoint? Can I just specify the URL and will Shopware download the image itself to a folder or keep pointing to the URL I have used. I need to house the images inside the Shopware.

There is no problem for me to download the images from the URL and push them to Shopware but I am not sure how to use the API for it (there is a lot of images and they need to be done in bulk).

2 Answers

One possible solution:

FIRST: create a new media POST /api/{apiVersion}/media?_response=true

SECOND: "Upload Image" /api/{apiVersion}/_action/media/{mediaId}/upload?extension={extension}&fileName={imgName}&_response=true

more information can be found here: https://forum.shopware.com/discussion/comment/278603/#Comment_278603

In CASE images are for products use the endpoint POST /api/{apiVersion}/product-media and set the coverId

A complete listing of all routes is available via the OpenAPI schema: [your-domain/localhost]/api/v3/_info/openapi3.json

It's also possible to set all the media and the cover & coverId during product creation by one request. Therefore, set the product Cover and product Media

{
"coverId":"3d5ebde8c31243aea9ecebb1cbf7ef7b",
"productNumber":"SW10002","active":true,"name":"Test",
"description":"fasdf",
"media":[{
"productId":"94786d894e864783b546fbf7c60a3640",
"mediaId":"084f6aa36b074130912f476da1770504",
"position":0,
"id":"3d5ebde8c31243aea9ecebb1cbf7ef7b"
},
{
"productId":"94786d894e864783b546fbf7c60a3640",
"mediaId":"4923a2e38a544dc5a7ff3e26a37ab2ae",
"position":1,
"id":"600999c4df8b40a5bead55b75efe688c"
}],
 "id":"94786d894e864783b546fbf7c60a3640"
}

Keep in mind to check if the bearer token is valid by checking for example like this:

if (JwtToken.ValidTo >= DateTime.Now.ToUniversalTime() - new TimeSpan(0, 5, 0))
{
    return Client.Get(request);
}
else
{
  // refresh the token by new authentication
  IntegrationAuthenticator(this.key, this.secret);
}
return Client.Get(request);

This will work for Shopware 6.4

As a general advice, it depends. The APIs changed a little bit since 6.4 and there is also an official documentation available at https://shopware.stoplight.io/docs/admin-api/docs/guides/media-handling.md.

However, i think that it is always a little easier to have a real life example. What i do in our production environment is basically these steps.

  1. (Optional) Check, if the media object exists
  2. Create an media-file object using the endpoint GET /media-files/
  3. If it exist then upload an image using the new media-id reference.

Let us assume the filename is yourfilename.jpg. What you also will need is a media-folder-id, which will reference the image-folder within Shopware. This can be obtained in Shopware via Admin > Content > Media > Product Media.

Step 0

Before uploading an image to Shopware, you want to ensure that the image does not exists, so that you can skip it.

This step is optional, as it is not mandatory to create an image. However you want to have some sort of validation mechanism in a production environment.

Request-Body

POST api/search/media

This will run a request against the Shopware-API with a response.

{
   "filter":[
      {
         "type":"equals",
         "field":"fileName",
         "value":"yourfilename"
      },
      {
         "type":"equals",
         "field":"fileExtension",
         "value":"jpg"
      },
      {
         "type":"equals",
         "field":"mediaFolderId",
         "value":"d798f70b69f047c68810c45744b43d6f"
      }
   ],
   "includes":{
      "media":[
         "id"
      ]
   }
}

Step 1

Create a new media-file

Request-Body

POST api/_action/sync

This request will create a new media-object in Shopware.

  1. The value for media_id must be any UUID. I will use this value: 94f83a75669647288d4258f670a53e69
  2. The customFields property is optional. I just use it to keep a reference of hash value which i could use to validate changed values.
  3. The value for the media folder id is the one you will get from your Shopware-Backend.

{
    "create-media": {
        "entity": "media",
        "action": "upsert",
        "payload": [
            {
                "id": "{{media_id}}",
                "customFields": {"hash": "{{file.hash}}"},
                "mediaFolderId": "{{mediaFolderId}}"
            }
        ]
    }
}

Response

The response will tell you that everything works as expected.

{
   "success":true,
   "data":{
      "create-media":{
         "result":[
            {
               "entities":{
                  "media":[
                     "94f83a75669647288d4258f670a53e69"
                  ],
                  "media_translation":[
                     {
                        "mediaId":"94f83a75669647288d4258f670a53e69",
                        "languageId":"2fbb5fe2e29a4d70aa5854ce7ce3e20b"
                     }
                  ]
               },
               "errors":[
                  
               ]
            }
         ],
         "extensions":[
            
         ]
      }
   },
   "extensions":[
      
   ]
}

Step 2

This is the step where we will upload an image to Shopware. We will use a variant with the content-type image/jpg. However, a payload with an URL-Attribute would also work. See the details in the official documentation.

Request-Body

POST api/_action/media/94f83a75669647288d4258f670a53e69/upload?extension=jpg&fileName=yourfilename

Note that the media-id is part of the URL. And also the filename but without the file-extension JPG!

This body is pretty straightforward an in our case there is no payload, as we use an upload with Content-Type: "image/jpeg".

This would be a payload if you want to use an URL as resource:

{
  "url": "<url-to-your-image>"
}
Related