Skip to main content
SocialCutter

CMS and websites

PrestaShop product images over the Webservice API

Generate the sizes with SocialCutter and upload them to PrestaShop over the Webservice image endpoint, assigned to the product.

  • PrestaShop
  • Webservice
  • images/products
  • API key
  • PHP
  • Python
  • product images

Why pre-generate the sizes

A PrestaShop product page shows the same photo in the grid, in the category listing, in the cart and in recommendations. Each slot crops to its own ratio, following the theme’s rules.

The flow is: one master goes in, SocialCutter returns every size, and PrestaShop gets the right one in each slot. The cover crop, which is the default mode, is centred: it scales the image and splits the excess evenly on both sides. Leave some margin in the master so nothing important is trimmed.

Where it goes in the storeSocialCutter destinationSize
Main product imageinstagram post1080x1080 (1:1)
Second portrait imageinstagram story1080x1920 (9:16)
Category bannerfacebook post1200x630 (1.91:1)
Store headertwitter header1500x500 (3:1)
Ad or external listingfacebook story1080x1920 (9:16)

Sizes come from GET /api/v1/platforms, which is public. There is no 4:5 in the catalogue: square is 1:1 and portrait is 9:16.

Versions and permissions

Versions. The Webservice exists on both 1.7 and 8, but it is not identical. Fields change, some resources do too, and authentication especially. Work from the documentation for your version:

Always probe with a read before writing: GET /api/products/12?output_format=JSON must return the product. The default format is XML; output_format=JSON returns JSON on the versions that support it, and ?schema=blank describes a resource’s schema.

Permissions. The key is created in Advanced Parameters → Webservice. Permissions are per resource and per verb:

ResourceVerbsWhat for
imagesGET, POST, DELETEUpload and list product images
productsGET, PUTAssociate the image and read the product
image_typesGETList the theme’s image types

If a verb is not ticked, the call fails with an authorisation error even when the key itself is correct.

Authentication. The current docs use the Authorization header with basic authentication: the key as the username and an empty password. Many installs still accept the key inside the URL (https://KEY@store.com/api/...) or the ws_key parameter. A key in the URL ends up in server logs, so prefer the header. curl -u "$PS_KEY:" builds that header for you.

export PS_URL="https://your-store.com"
export PS_KEY="WEBSERVICE_KEY"
export SC_KEY="sc_your_key"

1. Generate the sizes with SocialCutter

curl -s -X POST "https://api.socialcutter.theboomer.dev/api/v1/images/process" \
  -H "X-API-Key: $SC_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: product-12-catalogue" \
  -d '{
    "source": { "type": "url", "value": "https://your-cdn.com/master.jpg" },
    "destinations": [
      { "platform": "instagram", "format": "post" },
      { "platform": "instagram", "format": "story" }
    ]
  }' > sc.json

jq '.image_id, (.outputs[] | {url, platform, format, width, height})' sc.json

Every output is a public URL. Idempotency-Key makes retries safe. For a local master use POST /api/v1/images/process/upload (multipart, file field, 5 MB maximum) and for volume POST /api/v1/images/batch.

2. Upload the image to the product

The images resource takes the file through POST /api/images/products/<id> in a multipart request. Download the SocialCutter output first and upload it with the key in basic authentication:

curl -s -o square.jpg "$(jq -r '.outputs[0].url' sc.json)"

# -u with the key and an empty password builds the Authorization header
curl -s -o /dev/null -w "%{http_code}\n" -X POST \
  -u "$PS_KEY:" \
  -F "image=@square.jpg;type=image/jpeg" \
  "$PS_URL/api/images/products/12"

The same in PHP, with CURLFile to force the file to be sent as a file:

<?php
function ps_upload_image( string $base, string $key, int $product_id, string $path ): int {
    $ch = curl_init( $base . '/api/images/products/' . $product_id );
    curl_setopt_array( $ch, array(
        CURLOPT_POST           => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_USERPWD        => $key . ':',
        CURLOPT_POSTFIELDS     => array(
            'image' => new CURLFile( $path, mime_content_type( $path ), basename( $path ) ),
        ),
        CURLOPT_TIMEOUT => 60,
    ) );

    $body = curl_exec( $ch );
    $code = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
    curl_close( $ch );

    if ( $code >= 300 ) {
        throw new RuntimeException( 'PrestaShop returned HTTP ' . $code . ': ' . $body );
    }

    return $code;
}

And in Python, with requests:

import requests

with open("square.jpg", "rb") as handle:
    response = requests.post(
        f"{BASE}/api/images/products/12",
        auth=(KEY, ""),
        files={"image": ("square.jpg", handle, "image/jpeg")},
        timeout=60,
    )

response.raise_for_status()
print(response.status_code)

The file field name and multipart handling can differ between versions: if you get a 400, check the upload example for your version in the official docs before changing your code.

3. Check and associate

List what is attached to the product:

curl -s -u "$PS_KEY:" "$PS_URL/api/images/products/12?output_format=JSON" | jq '.image[]?.id'

If your version does not associate the image on its own, add its id to the associations → images element of the product XML and save the whole product with a PUT to /api/products/<id>. PrestaShop replaces the entire resource on every PUT, so send the full XML the GET returned, not a fragment.

To see which sizes the theme generates, query GET /api/image_types. The classic ones are small_default, medium_default, large_default, home_default and cart_default; on 1.7 and 8 the list depends on your theme configuration. Regenerating those thumbnails is triggered from the admin panel (Design → Image Settings), and there is no documented Webservice endpoint to fire it. That is why, when you need an exact size or a large batch, pre-generating with SocialCutter is cheaper than depending on a full catalogue regeneration.

Cost

  • 1 use per destination (platform and format) per request; repeated destinations are not charged twice.
  • Failed processings are refunded.
  • Plans include API and MCP: Free 3 uses/day, Basic 10, Pro 30, Agency 100.

Common errors

SymptomCauseFix
401 on every callKey mistyped, Webservice disabled or IP not allowedCheck Advanced Parameters → Webservice and the key’s IP list
401 with the key inside the URLYour version already requires the Authorization headerUse -u "$PS_KEY:" or auth=(KEY, "")
403 on uploadThe images resource has no POST permissionAdd the permission and save the key again
400 on uploadThe file field is missing or the MIME type is not an imageSend image as multipart with type=image/jpeg
The image uploads but is not visibleIt is not associated with the product, or thumbnails were not regeneratedAdd the id to associations and regenerate from the panel
XML rejected on PUTYou sent a fragment instead of the full resourceGET the product and edit that XML
429 from SocialCutterWallet quota exhaustedCheck GET /api/v1/wallet or upgrade the plan

Next steps

Frequently asked questions

Does the API key go in the URL or in a header?

It depends on the version. Older installs accept the key inside the URL (https://KEY@store.com/api/...) or as the ws_key parameter; the current docs recommend the Authorization header with basic authentication, using the key as the username and an empty password. Check which one your version accepts.

Which permissions does the Webservice key need?

Permissions are per resource and per verb. At minimum images with GET and POST (and DELETE if you clean up), products with GET and PUT to associate the image with the product, and image_types with GET to list the available types.

Does it work the same on PrestaShop 1.7 and 8?

The resource scheme is similar but not identical: fields change, some resources do too, and so does authentication. Use the documentation for the version you actually have installed, not another one.

Do I have to regenerate thumbnails afterwards?

Thumbnail regeneration is triggered from the admin panel, in the theme's image settings. If you upload the exact sizes you need with SocialCutter, you stop depending on that regeneration.

What does it cost to process one product?

1 use per destination, meaning per platform and format pair. Two destinations from the same master spend 2 uses; repeating a destination in one request is not charged twice.